One problem with using blocks and asynchronous dispatch is that you can get into a retain cycle – the block can retain ‘self’, sometimes in mysterious ways. For instance, if you reference an ivar directly, what appears in the code is ‘theIvar’, the compiler generates ‘self->theIvar’. Thus, ‘self’, as a strong variable, is retained, and the queue retains the block, and the object retains the queue.
Apple recommends first assigning ‘self’ into a weak automatic variable, then referencing that in a block (see 1). Since the block captures the variable along with its decorators (i.e. weak qualifier), there is no strong reference to ‘self’, and the object can get dealloced, and at that moment the weak captured variable turns to nil.
大致意思是:
Block 也會引起一些循環(huán)引用問題(retain cycle)—— Block 會 retain ‘self’该园,而 ‘self‘ 又 retain 了 Block取募。因為在 ObjC 中卧波,直接調(diào)用一個實例變量,會被編譯器處理成 ‘self->theVar’半等,’self’ 是一個 strong 類型的變量,引用計數(shù)會加 1臂寝,于是嫌蚤,self retains queue, queue retains block祭示,block retains self肄满。
Apple 官方的建議是,傳進 Block 之前质涛,把 ‘self’ 轉(zhuǎn)換成 weak automatic 的變量稠歉,這樣在 Block 中就不會出現(xiàn)對 self 的強引用。如果在 Block 執(zhí)行完成之前汇陆,self 被釋放了怒炸,weakSelf 也會變?yōu)?nil。
示例代碼:
__weak __typeof__(self) weakSelf = self;? ? dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[weakSelf doSomething];
});
clang 的文檔表示毡代,在 doSomething 內(nèi)阅羹,weakSelf 不會被釋放勺疼。但,下面的情況除外:
__weak __typeof__(self) weakSelf = self;? dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[weakSelf doSomething];
[weakSelf doOtherThing];
});
在 doSomething 中捏鱼,weakSelf 不會變成 nil执庐,不過在 doSomething 執(zhí)行完成,調(diào)用第二個方法 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 內(nèi)问潭,strongSelf 不會被釋放猿诸。
總結(jié)
1 在 Block 內(nèi)如果需要訪問 self 的方法婚被、變量狡忙,建議使用 weakSelf。(三方masonry址芯、系統(tǒng)自帶的animation方法以及灾茁,不互相持有的除外)
2 如果在 Block 內(nèi)需要多次 訪問 self,則需要使用 strongSelf谷炸。
系統(tǒng)自帶GCD線程block北专、數(shù)組字典的帶有usingblock方法的都會將blcok拷貝到堆,內(nèi)部用到self都要弱引用)
參考:
https://dhoerl.wordpress.com/2013/04/23/i-finally-figured-out-weakself-and-strongself/
http://stackoverflow.com/questions/21113963/is-the-weakself-strongself-dance-really-necessary-when-referencing-self-inside-a?rq=1