crash日志:
*** Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <XXXViewController 0x7ff158707f80> for the key path "xxx" from <XXXViewController 0x7ff158707f80> because it is not registered as an observer.'
分析原因:在使用KVO时,add observer和remove observer都是配对出现的,首先添加成为观察者,然后在释放内存的时候移除。例如:
override func viewDidLoad() {
super.viewDidLoad()
AppUnreadNumManager.instance.addObserver(self, forKeyPath: "xxx", options: .new, context: nil)
}
deinit {
AppUnreadNumManager.instance.removeObserver(self, forKeyPath: "xxx", context: nil)
}
通常情况下,这样写是没有问题的,但是有时候控制器可能还没有加载(viewDidLoad方法没走),然后就被释放了(deinit方法走了),这样就会出现上面那个bug。
我项目中出现这个bug的原因是:我在某个控制器开启KVO监听,正好它又是UITabBarController的子控制器,在没有选中该控制器的情况下,它的viewDidLoad方法是不会走的。如果这时候直接退出UITabBarController,那么该控制器就会直接被释放,这样就会出现还没添加观察者就移除观察者的bug。
解决方案:
var isViewDidLoad = false
override func viewDidLoad() {
super.viewDidLoad()
isViewDidLoad = true
AppUnreadNumManager.instance.addObserver(self, forKeyPath: "xxx", options: .new, context: nil)
}
deinit {
if isViewDidLoad {
AppUnreadNumManager.instance.removeObserver(self, forKeyPath: "xxx", context: nil)
}
}
文章分析了KVO在使用过程中由于未正确配对add observer和remove observer导致的crash问题。当控制器在未加载视图的情况下被释放时,可能会触发此错误。具体场景是在UITabBarController的子控制器中开启KVO监听,如果没有选中该控制器,退出时控制器会直接被释放,从而引发bug。解决方案是对添加和移除观察者进行适当处理,确保在正确的时间点进行操作。

被折叠的 条评论
为什么被折叠?



