一、循环引用,
以两个实例为例,循环引用产生于两个实例都强引用的对方,而两个实例的释放都依赖于对方的释放,最终都无法释放。
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等底层第三方的时候尤其要注意这一点。