Swift 4.0中pushVC出栈后不释放,内存泄漏问题排查
问题分析:pushVC弹出后无法释放的原因
咱们直接戳中核心:你在NotificationCenter的闭包中直接调用self.printSomeText(),触发了强引用循环(循环引用),导致pushVC无法被ARC自动释放。
具体原因拆解
- 当你在
viewDidLoad里调用NotificationCenter.default.addObserver并传入闭包时,NotificationCenter会对这个闭包保持强引用。 - 你的闭包中直接使用了
self(调用self.printSomeText()),Swift闭包默认会对self进行强引用。 - 这就形成了一个闭环的强引用链:
pushVC → 闭包 → NotificationCenter,同时NotificationCenter持有闭包,闭包又持有pushVC,ARC无法判断该何时释放这个对象,所以pushVC弹出后永远不会触发deinit。
而当你移除self.printSomeText()后,闭包不再捕获self,这个循环引用链直接被打破,pushVC弹出后没有其他强引用持有它,ARC就会正常释放它,deinit自然就会被调用。
解决方法
方法1:用弱引用打破循环引用
在闭包的捕获列表中声明[weak self],让闭包对self进行弱引用,这样闭包不会持有self的强引用,循环引用就不存在了:
override func viewDidLoad() { Log() NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "event_name"), object: nil, queue: nil) { [weak self] (notification) in self?.printSomeText() } }
这里用self?是因为弱引用的对象可能已经被释放,需要通过可选链式调用保证安全。
方法2:手动移除观察者(最佳实践)
虽然iOS 9及以后系统会在对象释放时自动移除NotificationCenter的观察者,但手动在deinit中移除观察者是更稳妥的做法,能避免一些特殊场景下的潜在问题:
deinit { NotificationCenter.default.removeObserver(self) Log() }
把这两个方法结合起来,就能彻底解决pushVC无法释放的问题啦。
内容的提问来源于stack exchange,提问作者AleyRobotics
相关产品推荐
相关产品推荐

