簡體   English   中英

在 iOS 13 中使用 UIScenes,如何 AirPlay 鏡像屏幕(似乎默認為外接顯示器)

[英]Using UIScenes in iOS 13, how do I AirPlay Mirror a screen (seems to default to external display)

如果我編譯到 iOS 12 設備(不使用 UIScene)和 AirPlay Mirror 到我的 Apple TV,則應用程序會按預期鏡像到電視。

在 iOS 13 設備上,它似乎將其視為外部顯示器,並對其進行格式化以適應屏幕(但我無法控制它)。

我更喜歡只是鏡像它的舊功能。

如何在 iOS 13 上完成鏡像? 我在文檔中四處尋找:

application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration

UISceneConfiguration中有一個role屬性(當我嘗試 AirPlay Mirror 時它有UISceneSession.Role.windowExternalDisplay ),但它似乎沒有像UISceneSession.Role.windowMirror這樣的任何值。

我一直在玩鏡像和外部顯示器,只有代碼/設置的正確組合存在各種可能性,但某些功能似乎不可能。

在 iOS 13(使用 iOS 13 的 Base SDK 構建的應用程序)下,您可以將應用程序鏡像到外部顯示器上。 但是使這項工作可以防止您的應用程序在外部顯示器上顯示不同的內容。 基本上,您的應用程序僅鏡像或僅顯示外部顯示器的獨特場景。

如果您希望只鏡像您的應用程序,請確保以下內容:

  1. 從您的 App Delegate 中刪除application(_:configurationForConnecting:options:)
  2. 在Info.plist中,確保“Application Scene Manifest”的“Scene Configuration”部分下沒有“External Display Session Role”條目。

如果這兩件事都不是您的應用程序的一部分,那么當您在 iOS 設備上激活屏幕鏡像時,您的應用程序將簡單地鏡像到任何外部屏幕。

我發現使用 Objective-C 實現,您可以通過在application:configurationForConnectingSceneSession:options:中返回nil來實現屏幕鏡像行為。

- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
    if (connectingSceneSession.role == UIWindowSceneSessionRoleExternalDisplay) {
        return nil;
    }
    UISceneConfiguration *configuration = [[UISceneConfiguration alloc] initWithName:@"Main" sessionRole:connectingSceneSession.role];
    configuration.storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    configuration.delegateClass = [SceneDelegate class];
    configuration.sceneClass = [UIWindowScene class];
    return configuration;
}

請注意,這不是記錄在案的方式,將來可能會中斷。

編輯:在 Swift 中,您可以通過調配方法實現此目的:

@UIApplicationMain
class AppDelegate : UIResponder, UIApplicationDelegate {

    override init() {
        _ = AppDelegate.performSceneConfigurationSwizzle
        super.init()
    }

    private static let performSceneConfigurationSwizzle: Void = {
        method_exchangeImplementations(
            class_getInstanceMethod(AppDelegate.self, #selector(AppDelegate.application(_:configurationForConnecting:options:)))!,
            class_getInstanceMethod(AppDelegate.self, #selector(AppDelegate.swizzle_application(_:configurationForConnecting:options:)))!
        )
    }()

    @objc func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        fatalError("Should never reach.")
    }

    @objc private func swizzle_application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration? {
        if connectingSceneSession.role == .windowExternalDisplay {
            return nil
        }
        // build scene configuration as usual…
    }
}

我自己也遇到了這個問題。 我的解決方案實際上來自我的UIWindowSceneDelegate class。

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        // External displays should not get assigned a window. When a window isn't assigned, the default behavior is mirroring.
        guard session.role != .windowExternalDisplay else { return }
        /* the rest of your setup */
    }

當您不分配 window 時,鏡像似乎成為默認選項。 在此更改之前,我的外部顯示器(屏幕鏡像)擁有自己獨特的 UIWindow 實例。

我沒有在任何地方看到這個文檔,而且它不直觀。 正因為如此,我有點擔心它將來會破裂。

希望它仍然有幫助。

而不是實現iOS 13中的AppDelegate場景配置方法:

@available(iOS 13.0, *)
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    let configuration = UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    configuration.delegateClass = SceneDelegate.self
    return configuration
}

我改為使用 Info.plist 變體(並刪除了上面的代碼),您可以在 Info.plist 中有效地指定上述所有內容。 (對於 Info.plist 文件中預期的最新版本,只需在 Xcode 中創建一個新項目,然后從新的 Info.plist 文件中復制Application Scene Manifest鍵的內容)。

它現在可以完美運行,AirPlay Mirror 可以按預期進行鏡像。 我確實嘗試將role更改為windowApplication ,因為 iOS 似乎與 Info.plist 變體一起使用,但它仍然不起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM