您的位置:首页 > 其它

KVO使用不当导致的崩溃

2017-08-21 18:11 197 查看
现象:对象被释放时崩溃

原因:对象有未移除的观察者

记录一下自己解决问题的过程,反思自己在解决问题过程中是不是方法得当:

今天遇到一个莫名崩溃——属性被赋值的时候崩溃。像这样



console没有任何提示。

楼主开始只注意到1、2,着手调查breakPoint 1.1是啥。走了一些弯路。其实真正的通关提示语在3。

可以从3中看到这样一个信息NSKVODeallocate,这就基本确定是kvo使用不当造成的。

kvo造成的崩溃我只遇到过两种,一种是释放对象时对象上有未移除的观察者,第二种是移除从未注册过或已移除过的观察者。

说到这,聪明的你是不是想到了什么

属性赋值意味着新属性对象的retain count+1,老属性对象的retain count-1,所以老属性对象有被释放的可能

容易联想到第一种崩溃情况(当然,这都是马后炮,事实上了楼主并没有想到这里。楼主只是去搜了“属性赋值 崩溃 iOS”😂)

好了吧,事情就是这么个事情,干货没有了,接下来我要继续讲我的探险历程了

当时我的内心是这样告诉我的:dealloc + kvo = 往dealloc的对象里面发消息造成的崩溃?

于是我看了崩溃时的内存图



箭头指的是看内存图的地方(xcode8)

红框中就是崩溃发生时的老属性(老self.dataSource)

看到了有被释放的对象,更加验证了我“是给被释放的对象发kvo相关消息导致崩溃的” 的观念。(发现楼主喜欢靠直觉去找问题。实际上这道题不考直觉,仔细分析,或许会更快。因为一些结论失之毫厘差之千里)

被释放的是老属性,崩溃应该在上面老属性移除观察者时崩溃,但是楼主想,也许这是编译器定位不准呢?然后楼主带着疑问进入下一项

然后楼主想苹果是在对象被dealloc的时候自动给观察者发消息了?还是我自己在setter、getter里做了什么?(现在看起来挺糊涂的。)

验证了我确实没在setter、getter里做啥,楼主找了一段代码来检测进入setData:Delegate:At方法时是否self.dataSource已经被释放了

结果是,没有

刚进入setData:Delegate:At方法时self.dataSource还是正常的,而后崩溃时,self.dataSource就被释放了(就是想不到被释放对象有没有移除的观察者会崩溃)

然后楼主想,这肯定是系统有啥我不知道的隐形操作或规则,毫无头绪的我打算战略性撤退

放弃这个问题后还是一直想着,然后最开始提到的情况一进入我的脑海,然后楼主想到了以前留下的一个坑——可能多次添加同一观察者到同一属性上

火速更改,然后测试,不崩溃了!!!

举一反三:

赋值崩溃的可能原因:

原属性被释放导致(未移除的观察者、给被释放的原属性发消息……)

欢迎补充
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐