你問:
假設weakSelf
是非nil
發送消息時,它可能會被同時doSomeAction
正在釋放或者是保證仍然有效,直到doSomeAction
回報?
是的,它不僅保持有效,直到doSomeAction
返回,它也保留在塊的其餘部分。考慮以下幾點:
- (void)dealloc
{
NSLog(@"%s", __FUNCTION__);
}
- (void)startBackgroundOperation
{
__weak MyObject * weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[weakSelf doSomeAction];
sleep(5);
[weakSelf doSomeAction2];
});
sleep(1);
}
- (void)doSomeAction
{
NSLog(@"%s", __FUNCTION__);
}
- (void)doSomeAction2
{
NSLog(@"%s", __FUNCTION__);
}
在這個例子中,我確保對象在範圍上,當塊開始,但讓它掉下來的doSomeAction
和doSomeAction2
之間的範圍,但該塊似乎保留它的該塊的完成。但是,如果我註釋掉doSomeAction
的調用,那麼weak
的引用是nil
,直到達到doSomeAction2
時爲止,就像您期望的那樣。
順便說一句,在WWDC 2011 - #322 - Objective-C Advancements In-Depth,他們指出(約27:00分鐘到視頻),他們指出,如果你提領weakSelf
,你應該有調度塊內的局部強引用保護自己的競爭條件,即:
__weak MyClass *weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
MyClass *strongSelf = weakSelf;
if (strongSelf)
[strongSelf->myView doSomeViewAction];
});
這將保留它的塊的時間(假設它是不是已經被執行該塊時釋放)。
來源
2013-02-23 03:53:59
Rob
這似乎對我來說是一個實現的怪癖;我懷疑這是記錄/保證任何地方。 :) – 2013-02-23 18:33:57
@Rob:這幾乎肯定是Steven說的一個實現問題。編譯器可能使用'objc_loadWeak()',它自動釋放該值,而不是'objc_loadWeakRetained()',而不是'objc_loadWeakRetained()'。你不能依賴這種行爲,因爲它可能隨着編譯器的優化級別或將來版本而改變。 – 2013-02-23 20:28:14
後續問題:那麼蘋果在LLVM 5.0中提供了「發送消息給__weak指針」警告的潛在問題?我注意到「反覆使用__weak引用」是一個單獨的警告。除非在優化參數之前進行'nil'檢查的優化(即它不僅發生在'objc_msgSend'中)? – Tommy 2013-10-29 21:34:38