我正在尝试向我的应用程序添加外部显示支持。该应用程序最初是使用 a 构建的AppDelegate
,但我已将其迁移到使用 a SceneDelegate
,因为我被告知它是 iOS 13 之后的外部显示支持所必需的。我更新了我的info.plist
,既有SceneDelegate
用于主应用程序的,也有ExtSceneDelegate
用于外部的我在几个不同的教程中看到的显示。代表和 plist 更改都发布在下面。
Info.plist 添加
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
<key>UIWindowSceneSessionRoleExternalDisplay</key>
<array>
<dict>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).ExtSceneDelegate</string>
<key>UISceneConfigurationName</key>
<string>External Configuration</string>
</dict>
</array>
</dict>
</dict>
SceneDelegate.swift
import Foundation
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
let window = UIWindow(windowScene: windowScene)
// Provide your apps root view controller
let initialViewController = RaiseBookViewController()
window.rootViewController = initialViewController
self.window = window
window.makeKeyAndVisible()
}
}
ExtSceneDelegate.swift
import Foundation
class ExtSceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
let window = UIWindow(windowScene: windowScene)
// Provide your apps root view controller
let hostingController = HostingControllerPresentable(rootView: DefaultPresentationView(appIcon: Bundle.main.icon ?? UIImage()))
window.rootViewController = hostingController
self.window = window
window.makeKeyAndVisible()
}
}
在我的应用程序中,我想根据用户的活动更新外部显示器。为此,我像这样注册通知:
func registerForScreenNotifications() {
let notificationCentre = NotificationCenter.default
notificationCentre.addObserver(self, selector: #selector(self.externalScreenDidConnect(notification:)), name: UIScreen.didConnectNotification, object: nil)
}
@objc func externalScreenDidConnect(notification: NSNotification) {
guard let screen = notification.object as? UIScreen else {
return
}
setupScreen(screen: screen, shouldRecurse: false)
}
然后尝试设置连接的第二个显示器。
@objc func setupScreen(screen: UIScreen, shouldRecurse: Bool) {
// For iOS13 find matching UIWindowScene
var matchingWindowScene: UIWindowScene?
if #available(iOS 13.0, *) {
let scenes = UIApplication.shared.connectedScenes
for aScene in scenes {
if let windowScene = aScene as? UIWindowScene {
// Look for UIWindowScene that has matching screen
if windowScene.screen == screen {
matchingWindowScene = windowScene
break
}
}
}
if matchingWindowScene == nil {
// UIWindowScene has not been created by iOS rendered yet
// Lets recall self after delay of two seconds
if true == shouldRecurse {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
self.setupScreen(screen: screen, shouldRecurse: false)
}
}
// Dont proceed furthure in iOS13
return
}
}
let vc = HostingControllerPresentable(rootView: DefaultPresentationView(appIcon: Bundle.main.icon ?? UIImage()))
var externalWindow = UIWindow(frame: screen.bounds)
externalWindow.rootViewController = vc
if #available(iOS 13.0, *) {
// Set windowScene here, no need to set screen
externalWindow.windowScene = matchingWindowScene
} else {
// Set screen the traditional way
externalWindow.screen = screen
}
externalWindow.isHidden = false
}
按原样运行代码时,由于ExtSceneDelegate
. 但是,如果我尝试更改外部显示器上显示的内容,该setupScreen
功能将找不到任何匹配的显示器。如果我在仅返回一个元素处设置断点let scenes = UIApplication.shared.connectedScenes
,即使实际上连接了两个显示器。我这辈子都想不通。并会感谢任何帮助。
注意:我知道在这段代码中,我试图在ExtSceneDelegate
和setupScreen
函数中为外部显示器设置相同的视图。我知道如果它正在工作,我不会注意到任何可见的变化,但我知道代码没有被执行,即使我尝试将它设置为不同的视图,也没有任何反应。