天天看點

IOS ARC下記憶體洩露總結

Block的循環引用

循環引用就是當self 擁有一個block的時候,在block 又調用self的方法。這個時候self強引用了block,而在block中使用self也會強引用self。這樣就會産生循環引用,導緻兩個對象都得不到釋放。

self.myBlock = ^{
    [self doSomething];
  };
           
IOS ARC下記憶體洩露總結

解決的方法:掐斷其中的一條強引用,使之變成弱引用,變成這樣,就打破了循環引用:

__weak typeof (self) weakSelf = self;
           
IOS ARC下記憶體洩露總結

還有一些系統的Block,這些Block中不用做特殊處理就可以直接使用self,因為這些系統的Block由系統strong引用,我們的代碼沒有強引用它

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)( * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    NSLog(@"Self.a %@", self.a);
});
           
IOS ARC下記憶體洩露總結

NSTimer未釋放

在使用 NSTimer addtarget 時,為了防止 target 被釋放而導緻的程式異常,timer 會強引用 target,是以這也是一處記憶體洩露的隐患。解決方法是使用線程安全的MSWeakTimer,然後在dealloc中主動調用invalidate

- (void)dealloc {
    [timer invalidate];
}
           

performSelector 系列

performSelector分靜态調用和動态調用,以下這種調用 selector 的方法和直接調用 selector 基本等效,執行效果相同,不存在記憶體洩露

[object methodName];
[object performSelector:@selector(methodName)];
           

還有一種動态綁定方式,編譯器不知道即将調用的 selector 是什麼,不了解方法簽名和傳回值,甚至是否有傳回值都不懂,是以編譯器無法用 ARC 的記憶體管理規則來判斷傳回值是否應該釋放。是以,ARC 采用了比較謹慎的做法,不添加釋放操作,即在方法傳回對象時就可能将其持有,進而可能導緻記憶體洩露。在ARC下編譯會告警:

warning: performSelector may cause a leak because its selector is unknow [-Warc-performSelector-leak]

-(void)method:(SEL)selector {
    [object performSelector:selector];
}
           

解決方式是使用函數指針,顯示的聲明這個函數

IMP imp = [viewController methodForSelector:selector];
void (*func)(id, SEL) = (void *)imp;
func(viewController, selector);
           

Delegate循環引用

把delegate聲明為strong屬性導緻了循環引用

@property (nonatomic, strong) SampleViewController *delegate;
           

解決方法很簡單把strong改成weak就行

@property (nonatomic, weak) SampleViewController *delegate;
           

循環未結束

如果某個ViewController中有無限循環,也會導緻即使ViewController對應的view關掉了,ViewController也不能被釋放。這種問題常發生于animation處理。

CATransition *transition = [CATransition animation];
transition.duration = ;
tansition.repeatCount = HUGE_VALL;
[self.view.layer addAnimation:transition forKey:"myAnimation"];
           

解決辦法是,在ViewController關掉的時候,停止這個animation

-(void)viewWillDisappear:(BOOL)animated {
    [self.view.layer removeAllAnimations];
}
           

非OBJC對象

ARC是自動檢測OBJC對象的,非objc對象就無能為力了,比如C或C++等。

C語言使用 malloc 開辟,free釋放。

C++使用new 開辟,delete釋放。

但是在ARC下,不會添加非OBJC對象釋放語句,如果沒去釋放,也會造成記憶體洩露。