【问题标题】:What is the proper way to get root view controller in iOS 13?在 iOS 13 中获取根视图控制器的正确方法是什么?
【发布时间】:2020-05-11 08:40:21
【问题描述】:
class TopViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        //Code Block 1
        let controller = getTopController()
        print(controller)// Prints out MyTestProject.TopViewController

        //Code Block 2
        let controller2 = getRootController()
        print(controller2)//Prints out nil , because keywindow is also nil upto this point.

        //Code Block 3
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5) {
            let controller2 = self.getRootController()
            print(controller2)// Prints out MyTestProject.TopViewController   
        }
    }

    func getTopController() -> UIViewController? {
        guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
            let sceneDelegate = windowScene.delegate as? SceneDelegate else {
                return nil
        }
        return sceneDelegate.window?.rootViewController
    }

    func getRootController() -> UIViewController? {
        let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
        let topController = keyWindow?.rootViewController
        return topController
    }
}

从 iOS 13 开始,有两种方法可以获取应用的当前活动/顶视图控制器。 这里: getTopController() 和 getRootController() 显示了这两种方法。

正如在代码中注释的那样,除了 print() 结果是不同的。

在代码块 2 中: getRootController 还找不到窗口,所以它打印出 nil。为什么会这样?

另外,iOS 13 中获取顶级控制器的完整证明方法,我现在很困惑?

【问题讨论】:

    标签: ios swift xcode application-lifecycle


    【解决方案1】:

    根据UIView 的文档,如果视图尚未添加到窗口中,则 window 属性为 nil,即调用 viewDidLoad 时的情况。

    尝试在 viewDidAppear 中访问它

    override func viewDidAppear(_ animated: Bool) {
       let controller2 = self.view.window.rootViewController
    }
    

    【讨论】:

      【解决方案2】:

      问题是当你的视图控制器viewDidLoadwindow.makeKey()还没有被调用时。

      如果关键窗口不可用,一个可能的解决方法是获取windows 数组中的第一个窗口。

          func getRootController() -> UIViewController? {
              let keyWindow = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) ?? UIApplication.shared.windows.first
              let topController = keyWindow?.rootViewController
              return topController
          }
      

      请注意,这将解决您的问题,但您应该推迟任何涉及使用键窗口的操作,直到它这样做为止。

      【讨论】:

      • 但为什么 getTopController() 方法的情况不同?即使在 viewDidLoad 中调用 Window 也不在那里。
      • 问题不在于窗口为nil,窗口存在但isKeyWindow为假,因为window.makeKey()还没有被调用。
      猜你喜欢
      • 2017-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-03
      • 2014-07-20
      相关资源
      最近更新 更多