MRC下delegate野指针问题
来源:互联网 发布:淘宝可以修改用户名吗 编辑:程序博客网 时间:2024/06/07 06:15
近项目开发中,临时被调去修复一个页面返回时crash的问题。出现这个问题的原因也很巧合,正好服务地址在同事电脑上,也正巧网络请求响应时间狂慢!一个请求发出去回来的时间是40秒左右,要是在线上,肯定会让用户抓狂死!
当我打开项目的时候,点击页面返回时,发现网络请求依然在请求中,第一感觉就是内存管理上出错。在全局断点中定位到出问题的点上,竟然是delegate回调的地方出现了问题!
if (self.delegate && [self.delegate respondsToSelector:@selector(test:)]) { [self.delegate test:nil]; }
这段代码在iOS开发中随处可见,而且其正确性在现在版本中毋庸置疑。一开始我并没有以为是delegate这边出错,因为我查了下property的确是assign。在ViewController里面又查了下相关内存操作,在dealloc中发现一个严重问题,我的VC都销毁了,里面对象竟然木有销毁,这的确很诡异。由于项目中结构有点奇葩,属于MVC重度用户!未销毁的对象就是我们所谓的负责业务逻辑的对象,在对其引用的地方只有网络请求的地方,在调用函数参数中delegate设置为self。在iOS开发中,我们会将网络请求放入到一个队列中,在网络请求成功后,在队列中取出网络请求相关信息,并移除此请求。由于在将网络请求加入到队列中对传进来的self进行了强引用,所以这个可以解释为什么我们业务处理对象引用计数为什么会大于1,而导致不能销毁。虽然这在设计上来说的确存在不合理性,我只需一个delegate而不需要对调用对象进行强引用。但仔细想想这个不至于导致程序挂掉,虽然我对你调用对象进行了引用计数加1,大不了内存迟点释放,走遍回调,我实际调用的VC已经是nil了所以也不会调用。
就是这个我认为VC一定是nil,毕竟我看到它在内存中销毁了。将Xcode debug中zombie objects勾上,重新调试,结果控制台中打印出 message sent to deallocated instance 0x90a3900,彻底改变了我的世界观!delegate不是nil。。。。可是我的delegate的确是assign啊!这是为什么呢?最根本的原因是将ARC中weak和MRC中的assign给混为一谈了。。。。
weak和assign对传入的对象不会改变引用计数的变化。所以发现我们的delegate,在MRC中是assign,在ARC中是weak。但是这两点有什么区别呢?两者都可以保证对传入的对象不会改变引用计数,但是weak对象必须是oc对象。weak比assign强大的地方就是在指向的对象销毁时,所有指向该对象的weak指针都会置为nil。这样我们就可以写出如此简洁的判断if (self.delegate && [self.delegate respondsToSelector:@selector(test:)])。而在MRC中,如果直接写这样的代码,如果调用者在对象销毁时未将delegate置为nil,delegate将变成野指针,而导致程序挂掉。所以在dealloc中[xxx release]前,加上xxx.delegate = nil。这也是为什么苹果官方推荐大家是用ARC,ARC在很多地方都可以保证程序的健壮性。
- MRC下delegate野指针问题
- Objective-c MRC内存管理-野指针
- MRC环境下block内存泄漏问题
- iOS MRC 下 block 循环引用问题
- MRC下 [NSMutableArray array] 经常导致崩溃的问题
- MRC和ARC下使用block的循环引用问题
- MRC下block循环嵌套暴露的内存问题
- MRC下计时器
- arc下使用mrc
- 函数指针delegate
- MRC下安全的Block
- ARC-MRC下的单例宏
- MRC下安全的Block
- MRC模式下的单例类
- mrc下自定义UITableViewCell写法
- MRC下的setter方法
- MRC 循环retain的问题
- 代码来解析MRC问题
- $.post() $.get() $.getJSON() | XML数据的处理
- 红黑树的Java实现
- eclipse安装svn和maven插件
- mac 下.svn 文件删除
- php namespace-命名空间
- MRC下delegate野指针问题
- appcan+在线打包完成如何安装到手机上
- 一个整数的每个数位都平方后求和,又得到一个整数,我们称这个整数为:位平方和。
- KafkaSpout的核心逻辑都是由PartitionManager来实现的。
- 第六周——项目四成员函数,友元函数,一般函数的区别
- Ajax用户名验证、服务条款加载、验证码生成
- 使用dump文件调试Release发布版程序的Crash错误
- 存储过程的一些经验
- 可伸展收缩的TextView