IOS中ARC模式下的crash之僵尸对象

本文详细探讨了iOS应用中常见的crash问题,特别是在ARC模式下因使用已释放对象导致的崩溃,并提供了有效的解决策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、问题

我们先来看下crash的实例场景:



控制台中,会显示"message sent to dealloccated instance"的信息,意思就是使用一个已经释放的对象。这个释放的对象,其实跟nil对象是不同,它不是nil,只是对象的内存被释放了。ios中,向一个nil对象发送消息,是不会crash的,应该是ios底层做了容错处理。说到这里,想起来C/C++中,内存的释放过程,比如

一般都需要在释放后,把指针置为NULL。但IOS中,非ARC模式下,assign修饰的对象不会被置为nil。



二、解决

在非arc下,对象的管理由开发者控制,retain、release等对引用计数的操作需要配对,如果产生了对象释放的错误以致crash问题,那就是开发者的问题,好好检查代码即可解决;但是arc模式下,对象的管理都交给ios自己去做,那我们开发者怎么去避免上述的问题呢?


ARC模式下,容易产生上述问题的场景主要有两个:一是方法内的局部对象,在其他方法使用; 二是异步过程的回调,比如网络操作。


(1) 局部对象

在其中一个方法内alloc的一个对象,出了该方法域,就会被释放,再到其他方法使用自然就不对。典型的应用就是视频播放:


只要MPMoviePlayerController *player;(局部),修改为全局或者属性或者项目修改为非ARC即可。


(2) 网络请求

网络请求一般都是异步的,有结果后然后回调。当网络有结果后,接收回调的对象可能已经释放,那么程序就会crash,参见最前面的贴图。

如果一个对象有判断是否被销毁的属性,或者判断引用计数是否为0,那就好办了。在非ARC下,有个retainCount属性可以获取对象的引用计数,但是arc下无法使用。更不幸的,即使有这些属性,但是对象都已经被销毁了,根本无法获取他们。

但是Apple还是考虑到了这些问题,它的官方文档,有如下说明:

所以,我们需要通过dealloc做一些事情。大家都知道ARC后是不能显示地调用dealloc方法,但是可以重载此方法,且重写子类dealloc时不能调用[super dealloc]。(arc下,虽然没有显式调用父类的[super dealloc],但结果仍然会调用,应该是编译期间编译器会聪明的帮我们加上了[super dealloc]。)

我们重载对象的dealloc方法,然后把里面的delegate设为nil。在设置nil的使用最好使用[self setOjbect:nil];


其实上面的场景一般是针对在arc模式下,还使用了assign修饰符,如果使用weak修饰符,如果对象被销毁,会直接被置为nil,就不会出现crash的问题。



参考:

1、http://www.3lian.com/edu/2013/10-14/101566.html

2、http://blog.youkuaiyun.com/musou_ldns/article/details/7673795

3、http://blog.youkuaiyun.com/ashqal/article/details/12614901

4、http://segmentfault.com/q/1010000000127093

5、http://blog.youkuaiyun.com/jofranks/article/details/21244625


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值