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。併發
Apple 官方的建議是,傳進 Block 以前,把 ‘self’ 轉換成 weak automatic 的變量,這樣在 Block 中就不會出現對 self 的強引用。若是在 Block 執行完成以前,self 被釋放了,weakSelf 也會變爲 nil。less
示例代碼:異步
1
2 3 4 |
__weak __typeof__(self) weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [weakSelf doSomething]; }); |
clang 的文檔表示,在 doSomething 內,weakSelf 不會被釋放。但,下面的狀況除外:async
1
2 3 4 5 |
__weak __typeof__(self) weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [weakSelf doSomething]; [weakSelf doOtherThing]; }); |
在 doSomething 中,weakSelf 不會變成 nil,不過在 doSomething 執行完成,調用第二個方法 doOtherThing 的時候,weakSelf 有可能被釋放,因而,strongSelf 就派上用場了:ide
1
2 3 4 5 6 |
__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 不會被釋放。wordpress
原文做者: 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