【问题标题】:Set rootViewController iOS 13设置rootViewController iOS 13
【发布时间】:2020-01-24 17:19:57
【问题描述】:

升级 Xcode 后,我的应用程序的一个关键部分停止工作。

当我的应用启动时,我会运行一个函数来检查布尔标志并设置正确的 rootViewController。

但是我用来设置它的代码现在已经停止工作

class func setLoginAsInitialViewContoller(window:UIWindow) {
    print("SET LOGIN") 
    let storyboard = UIStoryboard(name: "Login", bundle: nil)
    let controller = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
    controller.modalPresentationStyle = .overFullScreen
    window.rootViewController = controller
    window.makeKeyAndVisible()
}

特别是当应用程序获取倒数第二行 window.rootViewController = controller 时,它会崩溃并出现 libc++abi.dylib: terminating with uncaught exception of type NSException 错误。

上面的函数在一个名为 Utilities.swift 的类中,我正在我的 AppDelegate.swift 中调用该函数,如下所示:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var storyboard: UIStoryboard? = nil

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        UIApplication.shared.isIdleTimerDisabled = true
        Utilities.decideInitialViewController(window: self.window!)

        return true
    }

非常感谢任何关于如何设置根控制器的解决方案或修复。

谢谢!

【问题讨论】:

  • 这是控制台中的完整错误消息吗?
  • 您是否尝试过添加异常断点以获取有关崩溃的更多信息?
  • 应该有更多关于发生了什么异常的信息。
  • @Larme 是的,这是完整的错误,它给了我 'libc++abi.dylib: terminating with uncaught exception of type NSException' 其次是 '(lldb)'
  • 之前什么都没有?就像一个几乎一样的,有些字母大写和“NSUncaugthException”而不是“NSException”?

标签: ios swift ios13 uiwindow rootview


【解决方案1】:

这是因为 AppDelegate 不再具有 window 属性。 现在您必须使用 SceneDelegate 的 scene(_:willConnectTo:options:) 方法来更改根视图控制器。 如本例所示:

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let scene = (scene as? UIWindowScene) else { return }

        // Instantiate UIWindow with scene
        let window = UIWindow(windowScene: scene)
        // Assign window to SceneDelegate window property
        self.window = window
        // Set initial view controller from Main storyboard as root view controller of UIWindow
        self.window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()
        // Present window to screen
        self.window?.makeKeyAndVisible()
    }

【讨论】:

    【解决方案2】:

    它在您项目的 SceneDelegate.swift 文件中可用

    它将有委托方法:

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, 选项 connectionOptions: UIScene.ConnectionOptions)

    示例

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
     options connectionOptions: UIScene.ConnectionOptions) {
    
    
    if let windowScene = scene as? UIWindowScene {
    
        self.window = UIWindow(windowScene: windowScene) 
    
        let initialViewController = 
            storyboard.instantiateViewController(withIdentifier: "FirstViewController")            
            self.window!.rootViewController = initialViewController
            self.window!.makeKeyAndVisible()
        }
    
    }
    

    【讨论】:

    • 在哪里设置 rootViewController 的通知点击。早些时候我在 app_delegate func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { 中执行此操作。但是在设置 rootViewController 时发现它为零。
    • 这为我解决了一个不相关的问题。我曾经能够通过访问现在已弃用的 keyWindow 来获取 AppDelegate 中的 rootVC。果然,从 url 打开应用程序时,keywindow 是 none,而 rootVC 是 windowScene 对象上的一些。谢谢
    【解决方案3】:

    viewDidAppear中你可以设置root:-

      override func viewDidAppear(_ animated: Bool) {
                print(self.view.window)
                let vc = self.storyboard?.instantiateViewController(identifier: "SecondViewController") as? SecondViewController
                self.view.window?.rootViewController = vc
            }
    

    【讨论】:

      【解决方案4】:
      • 如果你想使用ScenceDelegate。在scene(_:willConnectTo:options: 中,创建一个新的 UIWindow,设置窗口的rootViewController 并使这个窗口成为key 窗口。
      • 如果您不想使用ScenceDelegate,可以尝试将其删除by following this

      【讨论】:

        【解决方案5】:

        对于希望创建几个扩展来更改根视图控制器并需要支持两种委托类型(UISceneDelegate 和 AppDelegate)的任何人,这里有几个:

            extension UIViewController {
                var appDelegate: AppDelegate {
                return UIApplication.shared.delegate as! AppDelegate
            }
            
            var sceneDelegate: SceneDelegate? {
                guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
                    let delegate = windowScene.delegate as? SceneDelegate else { return nil }
                 return delegate
            }
        }
        

        如果您需要扩展以从支持 iOS12 和 iOS13 的 ViewController 访问 UIWindow:

        extension UIViewController {
            
            var window: UIWindow? {
                if #available(iOS 13, *) {
                    guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
                        let delegate = windowScene.delegate as? SceneDelegate, let window = delegate.window else { return nil }
                           return window
                }
                
                guard let delegate = UIApplication.shared.delegate as? AppDelegate, let window = delegate.window else { return nil }
                return window
            }
        }
        

        【讨论】:

        • 另外,你能分享一下如何使用这些扩展的代码吗?假设我必须将“LoginVC”设置为我的 rootViewController。仅供参考:我的部署目标是 iOS 13.0
        • @Bhanuteja 确定使用这些扩展,您可以执行以下操作:例如 self.window?.rootViewController = LoginVC。
        猜你喜欢
        • 2020-01-30
        • 1970-01-01
        • 1970-01-01
        • 2020-11-09
        • 1970-01-01
        • 2016-07-05
        • 1970-01-01
        • 1970-01-01
        • 2020-01-09
        相关资源
        最近更新 更多