1.为避免循环引用,在使用代理时声明为weak对象
weak var delegate: MyDelegate
2.使用closure闭包时注意不要形成循环引用
lazy var someClosure: (Int, String) -> String = {
[unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
// closure body goes here
}
3.push出来的子控制器,导航栏控制器会对该子控制器进行强引用,其中 push 对应着 pop 则控制器会被销毁。其push的本质是入栈,所有的子控制器放在数组中,先进后出,如果导航栏作为根控制器。此时需要更该根控制器,不管push了多少子控制器入栈了。其最后只需要在当前显示的子控制器中对根控制器重新赋值即可。即原先的导航栏控制器没有对象强引用它,它会被释放,其所有的子控制器自然都会被释放了(前提是你本身代码不存在其他内存泄漏)
UIApplication.shared.keyWindow?.rootViewController = newRootVC
注意:只要有present出来的控制器,一定要有对应的dismiss,否则项目中会存在无法估量的bug。
ViewController push ---->firstVC1 present--->firstVC2 。则如何在firstVC2中切换根控制器,并同时销毁之前的控制器。则必须先dismiss掉 firstVC2 。
dismiss(animated: false) {
UIApplication.shared.keyWindow?.rootViewController = newRootVC
}
判断当前Controller 是否是被present出来的可以用一下方法判断
if self.presentingViewController != nil {
self.dismiss(animated: false, completion: {
UIApplication.shared.keyWindow?.rootViewController = tabBarController
})
}
4.Timer计时器使用时会默认形成强引用,在Timer有效的时候,引用Timer对象的对象不会执行deinit方法,所以不能再deinit里边设置self.timer?.invalidate(),self.timer = nil,要在确定需要释放这个对象的时刻调用先把Timer释放掉。