一、循環引用,
以兩個實例為例,循環引用產生于兩個實例都強引用的對方,而兩個實例的釋放都依賴于對方的釋放,最終都無法釋放。
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的終止??梢杂脀eakSelf代替,timer還是要主動invalidate。
三、UIImage加載圖片
[UIImage imageNamed:@""]的方式當加載時會緩存圖片,圖片如果使用頻繁可以用這種,否則推薦使用imageWithContentsOfFile。
四、C對象的創建和釋放
例如CoreFoundation對象 : 函數中用create\new\copy\retain產生的對象, 不用的時候需要調用CFRelease或者其他release函數,將其釋放掉。使用一些ffmpeg,opencv2等底層第三方的時候尤其要注意這一點。