微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么在窗口上交换根视图控制器时,在先前的根视图控制器上再次调用`viewDidAppear`方法?

如何解决为什么在窗口上交换根视图控制器时,在先前的根视图控制器上再次调用`viewDidAppear`方法?

在项目中,有时会交换根视图控制器以重新创建整个窗口层次结构。只需使用

即可调用漂亮的标准代码
windows.rootViewController = newController

,但是此代码立即在即将被销毁的视图控制器上调用viewDidAppear。它仅在根视图控制器上调用。在viewDidAppear上经过一段时间后,正确调用方法newController,但是为什么要在以前的视图控制器上调用它呢?

提取问题,我创建了一个新项目,并添加了产生该问题的最少代码量。因此,如果您创建一个新项目并仅将自动生成ViewController.swift修改为以下内容,就应该能够产生问题:

class ViewController: UIViewController {

    static var loadInstance: Int = 0
    var instance: Int = -1
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        ViewController.loadInstance += 1
        self.instance = ViewController.loadInstance
        
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print("Calling did appear on instance: \(instance)")
        
        let controller = AnotherController()
        controller.modalPresentationStyle = .fullScreen
        controller.view.backgroundColor = UIColor.red
        present(controller,animated: true,completion: nil)
    }

}

class AnotherController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addGestureRecognizer(UITapGestureRecognizer(target: self,action: #selector(onTap)))
    }
    
    @objc private func onTap() {
        print("Swapping root")
        UIApplication.shared.windows.first?.rootViewController = UIStoryboard(name: "Main",bundle: nil).instantiateInitialViewController()!
    }
}

根视图控制器需要提供至少一个其他视图控制器,该问题才能解决。它也需要全屏显示

在此示例中,当您按屏幕时,将创建一个新的控制器,该控制器交换根并显示一个新的红色视图控制器。每次这样做,您都可以看到以前的根控制器报告viewDidAppear调用的日志。日志如下所示:

Calling did appear on instance: 1
Swapping root
Calling did appear on instance: 1
Calling did appear on instance: 2
Swapping root
Calling did appear on instance: 2
Calling did appear on instance: 3

删除全屏设置会产生预期的结果:

Calling did appear on instance: 1
Swapping root
Calling did appear on instance: 2
Swapping root
Calling did appear on instance: 3

这是有原因还是仅仅是一个错误?无论如何:是否有解决方案,并且仍然可以安全地将viewDidAppear用于根控制器?

请注意,这只是该问题的最小介绍。实际的应用程序要复杂一些。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。