iOS __weak、__block使用
總之這一切其實就是為了防止迴圈引用,下面結合網路上各位大牛的分析精華分析分析
block對於其變數都會形成強引用(retain),對於self也會形成強引用(retain) ,而如果self本身對block也是強引用的話,就會形成 強引用 迴圈,無法釋放——造成記憶體洩露
什麼是迴圈引用:物件A持有物件B,物件B持有物件A,相互持有,最終導致兩個物件都不能釋放。
迴圈引用場景:
1、block在主函式體用到了self / self.變數 / [self 方法],意味著:block對self 進行持有操作;
2、self宣告瞭屬性變數block,block用copy來修飾,意味著:self對block進行持有操作,會造成迴圈引用;
例如下圖,現在這樣寫Xcode直接就會有警告出來告訴你這裡貌似retain cycle了啊!!
假如我想在block裡面改變區域性變數的值或者使用區域性變數,如下圖這麼寫Xcode直接報錯 而且給出瞭解決方法提示出來了 這點還挺機智的,那麼我們使用__block修飾之後,再次在block裡面使用,就不會出問題了,完美。
:
在使用block的地方:
__block typeof(self) bself = self; // 適用MRC模式,
__block NSString *tempStr = @"abc";
__block int a = 0; //當修飾變數時,表示這個變數值能在block中被修改
__weak typeof(self) weakself = self; // 適用ARC模式
關於——Block在MRC和ARC模式的區別
1)__block在MRC下有兩個作用
允許在Block中訪問和修改區域性變數
禁止Block對所引用的物件進行隱式retain操作
2)__block在ARC下只有一個作用
允許在Block中訪問和修改區域性變數
什麼時候在 block 中不需要使用 weakSelf???
- 大部分GCD方法,因為self並沒有對GCD的block進行持有,沒有形成迴圈引用。目前我還沒碰到使用GCD導致迴圈引用的場景,如果某種場景self對GCD的block進行了持有,則才有可能造成迴圈引用。
dispatch_async(dispatch_get_main_queue(), ^{
[self doSomething];
});
- 大部分動畫效果,當動畫結束時,UIView 會結束持有這個 block,block 物件就會釋放掉,從而 block 會釋放掉對於 self 的持有。整個記憶體引用關係被解除。
[UIView animateWithDuration:0.2 animations:^{
self.alpha = 1;
}];
- block並不是物件的屬性 / 變數,而是方法的引數 / 臨時變數,這裡因為block只是一個臨時變數,self並沒有對其持有,所以沒有造成迴圈引用
.- (void) testWithBlock:(void(^)())block {
block();
}
還有一種情況,block屬於Person物件,在另一個類裡面使用的時候沒有構成互相持有,這時候也不需要weakSelf。
使用GCD的時候,這麼寫其實是錯誤的,並不是見到block就要為了防止迴圈引用而使用weakSelf,像下面這種寫法,就是錯誤的:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf doSomething];
});
因為將block作為引數傳給dispatch_async時,系統會將block拷貝到堆上,而且block會持有block中用到的物件,因為dispatch_async並不知道block中物件會在什麼時候被釋放,為了確保系統排程執行block中的任務時其物件沒有被意外釋放掉,dispatch_async必須自己retain一次物件(即self),任務完成後再release物件(即self)。但這裡使用__weak,使dispatch_async沒有增加self的引用計數,這使得在系統在排程執行block之前,self可能已被銷燬,但系統並不知道這個情況,導致block執行時訪問已經被釋放的self,而達不到預期的結果。
總結
1 在 Block 內如果需要訪問 self 的方法、變數,建議使用 weakSelf。
2 如果在 Block 內需要多次 訪問 self,則需要使用 strongSelf。
相關文章
- iOS block巢狀block中weakify的使用iOSBloC巢狀
- iOS strong weak unowned引用iOS
- __weak與__block區別,深層理解兩者區別BloC
- iOS Block探究iOSBloC
- iOS--BlockiOSBloC
- iOS奇思妙想之使用block替代通知iOSBloC
- ios之Block研究iOSBloC
- IOS Block 塊用法iOSBloC
- ios 全面解析blockiOSBloC
- iOS Block淺淺析iOSBloC
- iOS - Block探究系列一iOSBloC
- iOS block 反向傳值iOSBloC
- iOS __block修飾符iOSBloC
- iOS-Block全解iOSBloC
- iOS5 strong, weak, unsafe_unretained ARCiOSAI
- iOS Block學習筆記iOSBloC筆記
- iOS探索:Block解析淺談iOSBloC
- iOS開發-Block實踐iOSBloC
- iOS之輕鬆上手blockiOSBloC
- iOS 進階—— iOS 記憶體管理 & BlockiOS記憶體BloC
- iOS中assign和weak修飾符的區別iOS
- iOS - 對 block 實現的探究iOSBloC
- iOS - block變數捕獲原理iOSBloC變數
- IOS中 Block簡介與用法iOSBloC
- iOS block種類和切換iOSBloC
- (轉載)iOS 底層解析weak的實現原理(包含weak物件的初始化,引用,釋放的分析)iOS物件
- iOS底層學習 - 記憶體管理之weak原理探究iOS記憶體
- iOS main()執行前的過程 + weak 置 nil的過程iOSAI
- iOS開發 Runtime是如何實現weak屬性的?iOS
- Block使用場景BloC
- 探索iOS中Block的實現原理iOSBloC
- iOS-block本質是什麼?iOSBloC
- iOS底層原理 - Block本質探究iOSBloC
- IOS中 Block簡介與用法(一)iOSBloC
- iOS 如果你使用過block,最好看一下這篇文章iOSBloC
- iOS-字典+block代替switch-(解決switch不能使用NSString)iOSBloC
- iOS 從原始碼深入探究weak的實現 | 掘金技術徵文iOS原始碼
- 使用 Block 實現 KVOBloC