轉載,原文: http://blog.lessfun.com/blog/2014/11/22/when-should-use-weakself-and-strongself-in-objc-block/
當然有一個更詳細的專題: http://tanqisen.github.io/blog/2013/04/19/gcd-block-cycle-retain/
Objective C 的 Block
是一個很實用的語法,特別是與GCD結合使用,可以很方便地實現並發、異步任務。但是,如果使用不當,Block 也會引起一些循環引用問題(retain cycle
)—— Block 會 retain ‘self’,而 ‘self‘ 又 retain 了 Block。因為在 ObjC 中,直接調用一個實例變量,會被編譯器處理成 ‘self->theVar’,’self’ 是一個 strong 類型的變量,引用計數會加 1,於是,self retains queue, queue retains block,block retains self。
解決 retain circle
Apple 官方的建議是,傳進 Block 之前,把 ‘self’ 轉換成 weak automatic 的變量,這樣在 Block 中就不會出現對 self 的強引用。如果在 Block 執行完成之前,self 被釋放了,weakSelf 也會變為 nil。
示例代碼:
__weak __typeof__(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[weakSelf doSomething];
});
clang 的文檔表示,在 doSomething 內,weakSelf 不會被釋放。但,下面的情況除外:
__weak __typeof__(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
__strong __typeof(self) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doOtherThing];
});
在 doSomething 中,weakSelf 不會變成 nil,不過在 doSomething 執行完成,調用第二個方法 doOtherThing 的時候,weakSelf 有可能被釋放,於是,strongSelf 就派上用場了:
__weak __typeof__(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
__strong __typeof(self) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doOtherThing];
});
__strong
確保在 Block 內,strongSelf 不會被釋放。
總結
- 在 Block 內如果需要訪問 self 的方法、變量,建議使用 weakSelf。
- 如果在 Block 內需要多次 訪問 self,則需要使用 strongSelf。
參考
- I finally figured out weakSelf and strongSelf
- Is the weakSelf/strongSelf dance really necessary when referencing self inside a non-retained completion called from a UIViewController?
原文作者: lslin
原文鏈接: http://blog.lessfun.com/blog/2014/11/22/when-should-use-weakself-and-strongself-in-objc-block/
版權聲明:自由轉載-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0