【问题标题】:Setter for 'screen' was deprecated in iOS 13.0iOS 13.0 中已弃用“屏幕”的设置器
【发布时间】:2020-07-26 04:53:11
【问题描述】:

我试图按照本教程创建一个多屏应用程序:

https://www.youtube.com/watch?v=UYviLiI2rlY&t=774s

不幸的是,在 25:00 - 26:00 分钟,我收到一条错误消息,并且我的外部屏幕一直黑屏:

[Assert] Error in UIKit client: -[UIWindow setScreen:] should not be called if the client adopts
UIScene lifecycle. Call -[UIWindow setWindowScene:] instead.

我的代码是:

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var textView: UITextView!
    var additionalWindows = [UIWindow]()

    override func viewDidLoad() {
        super.viewDidLoad()

        NotificationCenter.default.addObserver(forName: UIScreen.didConnectNotification, object: nil, queue: nil) { [weak self] notification in
            guard let self = self else {return}

            guard let newScreen = notification.object as? UIScreen else {return}
            let screenDimensions = newScreen.bounds

            let newWindow = UIWindow(frame: screenDimensions)
            newWindow.screen = newScreen

            guard let vc = self.storyboard?.instantiateViewController(withIdentifier: "PreviewViewController") as? PreviewViewController else {
                fatalError("Unable to find PreviewViewController")
            }

            newWindow.rootViewController = vc
            newWindow.isHidden = false
            self.additionalWindows.append(newWindow)
        }
    }


}

我在newWindow.screen = newScreen : Setter for 'screen' was deprecated in iOS 13.0 中有一个弃用警报,但我找不到任何有用的东西,而且对于如何解决这个问题也不过分复杂。

【问题讨论】:

标签: ios swift ios13 uiwindow uiwindowscene


【解决方案1】:

请注意,您“应该”根据 externalWindow.rootViewController

实例化一个 VC

在我的例子中,我使用外部显示器来呈现custom UIView(),所以我使用了一个空的UIViewController(),然后将我的视图添加到它。

private func setupExternalScreen(screen: UIScreen, retryUntilSet: Bool = true, retryTimesUntilDiscarded: Int = 0) {
    var matchingWindowScene: UIWindowScene? = nil
    let scenes = UIApplication.shared.connectedScenes
    for item in scenes {
        if let windowScene = item as? UIWindowScene {
            if (windowScene.screen == screen) {
                matchingWindowScene = windowScene
                break
            }
            }
    }
    if matchingWindowScene == nil {
        if true == retryUntilSet {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                if retryTimesUntilDiscarded < 5 {
                        self.setupExternalScreen(screen:screen, retryUntilSet: false, retryTimesUntilDiscarded += 1)
                } else {
                    let alert = UIAlertController(title: "Not connected", message: "Reconnect the display and try again", preferredStyle: .alert)
                        let ok = UIAlertAction(title: "Ok", style: .default, handler: nil)
                        alert.addAction(ok)
                        self.present(alert, animated: true, completion: nil)
                }
            }
        }
        return
    }
    externalWindow = UIWindow(frame: screen.bounds)
    externalWindow.rootViewController = UIViewController()
    airplayView.frame = externalWindow.frame
    if !externalWindow.subviews.contains(airplayView) {
        externalWindow.rootViewController?.view.addSubview(airplayView)
        if let _ = view.window {
            view.window?.makeKey()
        }
    } else {
        airplayView.updateValues()
    }

    externalWindow.windowScene = matchingWindowScene
    externalWindowWindow.isHidden = false
}

如果您的应用需要 iOSif #available(iOS 13.0, *) {} 决定如何设置您的外部屏幕。

忘了提...externalWindow 在我要求使用第二个屏幕的 ViewController 中声明

lazy var externalWindow = UIWindow()

【讨论】:

    【解决方案2】:

    连同here 提供的答案,我能够让它在模拟器中工作。对于 iOS 13+,您似乎必须在 UIApplication.shared.connectedScenes 中找到场景。

    import UIKit
    
    class ViewController: UIViewController {
        @IBOutlet weak var textView: UITextView!
        var additionalWindows = [UIWindow]()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            NotificationCenter.default.addObserver(forName: UIScreen.didConnectNotification, object: nil, queue: nil) { [weak self] notification in
                guard let self = self else {return}
                
                guard let newScreen = notification.object as? UIScreen else {return}
                // Give the system time to update the connected scenes
                DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                    // Find matching UIWindowScene
                    let matchingWindowScene = UIApplication.shared.connectedScenes.first {
                        guard let windowScene = $0 as? UIWindowScene else { return false }
                        return windowScene.screen == newScreen
                    } as? UIWindowScene
                    
                    guard let connectedWindowScene = matchingWindowScene else {
                        fatalError("Connected scene was not found") // You might want to retry here after some time
                    }
                    let screenDimensions = newScreen.bounds
                    
                    let newWindow = UIWindow(frame: screenDimensions)
                    newWindow.windowScene = connectedWindowScene
                    
                    guard let vc = self.storyboard?.instantiateViewController(withIdentifier: "PreviewViewController") as? PreviewViewController else {
                        fatalError("Unable to find PreviewViewController")
                    }
                    
                    newWindow.rootViewController = vc
                    newWindow.isHidden = false
                    self.additionalWindows.append(newWindow)
                }
            }
        }
    }
    

    我不确定时间,.now() + 1 似乎可以在模拟器上运行,但我还没有在真实硬件上尝试过,所以你可能需要调整一下。

    【讨论】:

      猜你喜欢
      • 2020-01-12
      • 2020-09-07
      • 1970-01-01
      • 2020-03-04
      • 1970-01-01
      • 2019-11-29
      • 1970-01-01
      相关资源
      最近更新 更多