一、切换rootViewController之前,present某一控制器
self.window = UIWindow.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
self.window?.rootViewController = UINavigationController(rootViewController: ViewControllerA())
self.window?.makeKeyAndVisible()
self.present(ViewControllerB(), animated: true, completion: nil)
在切换rootViewController的时候,必须先dismiss当前控制器,否则将产生内存泄漏:
self.dismiss(animated: false) {
let window = UIApplication.shared.keyWindow
window?.rootViewController = UINavigationController(rootViewController: ViewControllerA())
window?.makeKeyAndVisible()
}
原因分析:因为ViewControllerA present ViewControllerB,即ViewControllerA引用ViewControllerB,自动引用计数+1。在切换rootViewController之后,window的rootViewController不再引用UINavigationController,UINavigationController的计数器为0,随后被释放,与此同时栈内的ViewControllerA也会被释放。但是,ViewControllerA始终没有release ViewControllerB,导致ViewControllerB的计数器始终不为0,从而导致内存泄漏。
二、切换rootViewController之前,push某一控制器
self.navigationController?.pushViewController(ViewControllerB(), animated: true)
在切换rootViewController的时候,直接切换即可,不用担心内存泄漏:
let window = UIApplication.shared.keyWindow
window?.rootViewController = UINavigationController(rootViewController: ViewControllerA())
window?.makeKeyAndVisible()
原因分析:因为ViewControllerA push ViewControllerB,它们均被压入到UINavigationController栈中。在切换rootViewController之后,window的rootViewController不再引用UINavigationController,UINavigationController的计数器为0,随后被释放,与此同时栈内的ViewControllerA、ViewControllerB也都会被释放。
最后,在切换window的rootViewController时候,还需要注意切换前后的window是否是同一个window,否则也会造成内存泄漏,所以建议在项目中有切换rootViewController的地方都看一下视图的层级。