`
guafei
  • 浏览: 322447 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

IOS crash 总结

阅读更多
顽兔crash总结
Crash引起的原因:release一个retainCount为0的对象,一般对象的引用计数控制不当,导致内存泄露,非常容易造成程序的crash,其他的像数组越界、1/0等这种也会引起crash。顽兔期间造成crash的原因总结了下:

引用计数:
顽图客户端里面没有用ARC,所有对象的引用计数都是我们自己控制的。
只有在alloc,copy,retain三种情况下的对象的引用计数才会加1,通过release,autorelease引用计数减1。
执行release会立即使得retainCount减1,一般确定不用的对象使用。
执行autorelease延时引用计数减1,该对象不会立即被释放,而是将该对象放到自动回收池中,当最近的一个pool被释放之后,该对象才会被执行dealloc释放,有些同学可能会说,那么可以都用autorelease来处理好了,一般不这样做,比如alloc一个很大的对象,或者你执行一个for循环,每个循环里面可能都alloc了一个值,处理完了又确定不需要,那么立即释放肯定会比较好。
属性赋值:
我们看下我们在.h文件中定义一个属性userName
@property (retain,nonatomic)NSString *userName;
这个语句是自动生成属性的get set方法的,我们看下这个属性的set方法
-(void)setUserName(NSString *)userName{
[userName retain];
[_userName release];
_userName = userName;
}
发现执行set方法的时候,属性加_userName的retainCount加1了。
赋值代码self.userName = @”tbtest93”;其实就是执行了userName的set方法,所以_userName的retainCount已经加1。
赋值代码_userName = @”tbtest93”;只是简单的引用赋值而已,它的引用计数没有加1,所以在它的retainCount还是0,在函数执行完成之后对象就dealloc掉了。其它地方引用就会出问题

其它:
@property的属性如果把retain设置成assgin,那么引用计数不会加1,只是简单的赋值
@property的属性nonatomic是非原子操作,在多线程情况下需要用atomic。而且默认为atomic,当有多个属性为atomic时候,每一个属性都是访问都会锁定整个对象。
在ios5之后,支持ARC之后又了Strong和week属性,strong和retain一样,但是week和assgin有点小区别,使用week之后,属性dealloc之后,它会把指针置为nil,你调用了它的一个方法,它也不会crash。assign则不会。
delegate:
之前碰到过一个问题,是由于delegate导致的内存溢出。
在顽兔新版本的WTOtherVC.m方法中,有个成员变量WTUserInfoView,并且它的引用类型是retain,而 WTUserInfoView 有个delegate方法,这个delegate的引用类型retain类型,看下WTOtherVC 里面的方法。

{
    userInfoView.delegate = self;(WTUserInfoView retain住了这个WTOtherVC )
    ......................
self.userInfoView = userInfoView;(WTOtherVC retain住了这个WTUserInfoView )
}
这样就导致两个对象都释放不了,造成内存泄露。
看了下我们常用的tableView的delegate属性,它的引用类型也是assgin的,而不是retain,就是防止互相retain住。
viewDidunload:
在内存警告的情况下,会执行viewDidunload方法,在这个方法里面会当前被盖住的view给释放掉,如果处理不当,非常容易造成crash.一般我们会在viewDidunload里面把view设置为nil,self.xxxView=nil。一般在viewDidunload方法中不会去清空dataSource,因为下次viewDidload的时候,如果dataSource存在的话就没有必要在发起一次网络请求。
如果controller注册了NSNotification,那么返回的时候回调的方法如果没有view的相关处理,那么没有必要把这个NSNotification置为nil,但是如果对view有操作,那么必须把NSNotification给remove掉。同理Request也一样,如果回调方法没有涉及view的操作,那么Request没有必要置为nil,相反要设置为nil。一般我们都会在viewDidunload中把NSNotification,Request设置成nil。
Request:
如果你的view或者ViewController中发起了网络请求,那么你需要再viewDidunload和dealloc中把这个请求给cancel掉,因为在内存警告或者对象被释放掉时候,网络返回的数据找不到对应的处理方法,就会crash。
NSNotification:
如果你的ViewController 增加了一个Observer,那么你需要在viewDidunload和dealloc中把这个Observer移除掉,因为在内存警告或者对象被释放掉,post的notification找不到对应处理的方法,就会crash。
tableView:
tableView的delegate方法中,cell的个数或者dataSource中的数据处理不当,会导致数组越界,也容易发生crash.
Xib:我们大部分View都是用xib创建,在用xib拖拽属性到类中,会在dealloc方法里自动生成[xxx release],你重复拖的话,在dealloc里面也会重复生成[xxx release],这样就会导致一个对象在释放时重复被release,就会crash。建议在viewDidunload和dealloc方法里面把属性值统一设置为self.xxx=nil.
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics