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就被释放了(就是想不到被释放对象有没有移除的观察者会崩溃)
然后楼主想,这肯定是系统有啥我不知道的隐形操作或规则,毫无头绪的我打算战略性撤退
放弃这个问题后还是一直想着,然后最开始提到的情况一进入我的脑海,然后楼主想到了以前留下的一个坑——可能多次添加同一观察者到同一属性上
火速更改,然后测试,不崩溃了!!!
举一反三:
赋值崩溃的可能原因:
原属性被释放导致(未移除的观察者、给被释放的原属性发消息……)
欢迎补充
原因:对象有未移除的观察者
记录一下自己解决问题的过程,反思自己在解决问题过程中是不是方法得当:
今天遇到一个莫名崩溃——属性被赋值的时候崩溃。像这样
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就被释放了(就是想不到被释放对象有没有移除的观察者会崩溃)
然后楼主想,这肯定是系统有啥我不知道的隐形操作或规则,毫无头绪的我打算战略性撤退
放弃这个问题后还是一直想着,然后最开始提到的情况一进入我的脑海,然后楼主想到了以前留下的一个坑——可能多次添加同一观察者到同一属性上
火速更改,然后测试,不崩溃了!!!
举一反三:
赋值崩溃的可能原因:
原属性被释放导致(未移除的观察者、给被释放的原属性发消息……)
欢迎补充
相关文章推荐
- 基本c功能使用不当导致崩溃
- RabbitMQ使用不当导致的队列堵塞问题及解决办法
- WebView shouldOverrideUrlLoading 方法使用不当导致 服务端获取父url 失败
- Dispatcher.BeginInvoke()方法使用不当导致UI界面卡死的原因分析
- Messenger使用不当导致的内存泄漏
- TransitionDrawable使用不当导致内存泄露
- linux 使用不安全的sprintf函数,存储字符越界导致程序莫名崩溃问题
- Mybatis foreach标签使用不当导致异常的原因浅析
- ImageView的scaleType设置不当,导致使用Glide时出现OOM
- 规避QT4.8.5版本下ocx(dll的情况下)使用QNetworkAccessManager导致程序退出时产生的崩溃问题
- form 的 encoding设置不当导致在jsp中使用request.getParametre(paraName)无法获取表单提交的值
- Dispatcher.BeginInvoke()方法使用不当导致UI界面卡死的原因分析
- RabbitMQ使用不当导致的队列堵塞问题及解决之道
- Dispatcher.BeginInvoke()方法使用不当导致UI界面卡死的原因分析
- 在iOS10中使用stringWithUTF8String时字符串部分显示错误,转换失败导致string为空,程序崩溃
- 使用Multipletheme框架导致的应用崩溃
- ios 使用运行时规避数组等越界导致程序崩溃
- android:configChanges配置不当,应用被回收重启,导致应用崩溃
- MFC项目使用webbrowser控件,点击载入的页面里的文件下载链接后导致程序的崩溃问题的解决方案
- souce insight使用不当,导致软件卡顿,没有响应。