常见内存泄漏情况梳理

2017-03-10  本文已影响0人  夜明u

一、循环引用,

以两个实例为例,循环引用产生于两个实例都强引用的对方,而两个实例的释放都依赖于对方的释放,最终都无法释放。

1.delegate修饰成了strong,

2.block引起。

block引起循环引用要注意,block也是一个对象,当block被对象A持有,在block代码块中直接调用对象A相当于block对象强引用了对象A。举两个第三方库对比看看,

Masonry:

[buttonA mas_makeConstraints:^(MASConstraintMaker*make){

make.width.equalTo(@100);

make.height.equalTo(@100);

make.left.equalTo(self.view.mas_left);

make.top.equalTo(self.view.mas_top);

}];

这里直接用self是因为这个block没有被持有,执行完就被释放了,看源码可知

-(NSArray*)mas_makeConstraints:(void(^)(MASConstraintMaker*))block{

self.translatesAutoresizingMaskIntoConstraints=NO;

MASConstraintMaker*constraintMaker=[[MASConstraintMakeralloc]initWithView:self];

block(constraintMaker);

return[constraintMakerinstall];

}

AFNetworking:

AFNetworking源码可知,其内部使用了嵌套结构,以保证在回调的时候不会已经被释放,类似这样

__weakNSObject*weakSelf =self;

void(^block)(void) = ^{

//NSLog(@"b_name = %@",b_name);

__strongNSObject*strongSelf = weakSelf;

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1*NSEC_PER_SEC)),dispatch_get_main_queue(), ^{

NSLog(@"b_name = %@",strongSelf);//此处即为回调

});

};

block();

二、NSTimer

NSTimer *tt  =[NSTimerscheduledTimerWithTimeInterval:1target:self selector:@selector(timerMethod:)userInfo:nilrepeats:YES];

[tt fire];

这种方式直接创建的timer,将target设置成self,会导致之self的释放依赖于timer的终止。可以用weakSelf代替,timer还是要主动invalidate。

三、UIImage加载图片

[UIImage imageNamed:@""]的方式当加载时会缓存图片,图片如果使用频繁可以用这种,否则推荐使用imageWithContentsOfFile。

四、C对象的创建和释放

例如CoreFoundation对象 : 函数中用create\new\copy\retain产生的对象, 不用的时候需要调用CFRelease或者其他release函数,将其释放掉。使用一些ffmpeg,opencv2等底层第三方的时候尤其要注意这一点。

上一篇下一篇

猜你喜欢

热点阅读