现象:对象被释放时崩溃
原因:对象有未移除的观察者
记录一下自己解决问题的过程,反思自己在解决问题过程中是不是方法得当:
今天遇到一个莫名崩溃——属性被赋值的时候崩溃。像这样
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就被释放了(就是想不到被释放对象有没有移除的观察者会崩溃)
然后楼主想,这肯定是系统有啥我不知道的隐形操作或规则,毫无头绪的我打算战略性撤退
放弃这个问题后还是一直想着,然后最开始提到的情况一进入我的脑海,然后楼主想到了以前留下的一个坑
火速更改,然后测试,不崩溃了!!!