在iOS 13中获取根视图控制器的正确方法是什么?


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中获取顶级控制器引用的完整证明方法,我现在很困惑?

问题是当你的视图控制器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
}

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

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

尝试在视图中访问它确实出现

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

相关内容

最新更新