0

我最近學到了這個技巧,當我必須在塊中引用self時。用ARC在雙塊中捕獲自我

__weak MyObject *safeSelf = self; 
[self doWithCompletionBlock:^{ 

    HMFInventoryBatchItemsController *strongSelf = safeSelf; 
    if (strongSelf) { 
     [strongSelf doSomethingElse]; 
    } 
}]; 

但我一直在想,如果我有一個塊內的塊?我是否需要再次做同樣的事情?

__weak MyObject *safeSelf = self; 
    [self doWithCompletionBlock:^{ 

     HMFInventoryBatchItemsController *strongSelf = safeSelf; 
     if (strongSelf) { 

      __weak MyObject *saferSelf = strongSelf; 
      [strongSelf doAnotherThingWithCompletionBlock:^{ 

       HMFInventoryBatchItemsController *strongerSelf = saferSelf; 
       if (strongerSelf) { 
        [strongerSelf doSomethingElse]; 
       } 
      }]; 
     } 
    }]; 

或者是這個罰款

__weak MyObject *safeSelf = self; 
    [self doWithCompletionBlock:^{ 

     HMFInventoryBatchItemsController *strongSelf = safeSelf; 
     if (strongSelf) { 

      [strongSelf doAnotherThingWithCompletionBlock:^{ 

        [strongSelf doSomethingElse]; 

      }]; 
     } 
    }]; 
+1

爲什麼使用HMFInventoryBatchItemsController重新分配自己* strongSelf = safeSelf;既然自己是塊的所有權? –

+0

除非你想訪問它的ivar,否則你不必在block中做出強有力的參考。 – Elden

+0

我發現這篇文章作爲參考http://amattn.com/2011/12/07/arc_best_practices.html – Hackmodford

回答

2

好的答案是,這取決於。這是一般不安全的事:

__weak MyObject *safeSelf = self; 

[self doWithCompletionBlock:^{ 
     [safeSelf doAnotherThingWithCompletionBlock:^{ 
       [safeSelf doSomethingElse]; 
     }]; 
}]; 

其原因,就是當你調用-doAnotherThingWithCompletionBlock如果認爲該方法是持有self參考,其選擇通常假設,它取消引用自要訪問ivars,那麼你會崩潰,因爲你實際上沒有參考。

因此,您是否需要採用新的弱引用取決於您所需要的生命週期語義。

編輯:

順便說一句,鐺甚至有一個關於這個問題,你可以在Xcode中啓用與CLANG_WARN_OBJC_RECEIVER_WEAK設置警告(CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK也是有用的,而我們在這)

+0

你可能是指「方法」而不是「選擇器」。你可能也意味着「引用ivars」而不是「解除引用ivars」,意味着'self-> someIvar;';) – CouchDeveloper

+0

確實,我剛剛重新回答了我的回答 – JTAS

+0

好,現在看起來不錯。 ;) – CouchDeveloper

0
__block MyObject *safeSelf = self; 

    [self doWithCompletionBlock:^{ 
      [safeSelf doAnotherThingWithCompletionBlock:^{ 
        [safeSelf doSomethingElse]; 
      }]; 
    }]; 

希望它會做自己應該一般不會。告訴編譯器不要保留__weak MyObject *,不管它在哪個塊範圍內。事實是我沒有測試過。同時我會很驚訝,如果它實際上會保留MyObject *

+0

有什麼方法可以測試這個嗎? – Hackmodford

+0

你可以使用retaincount並觀察在block中是否有+1計數(當然,可以保證一個簡單的代碼可以保證「self」不被保留在其他地方)。第二種方法是在使用塊調用後釋放對象(假設您的塊是ivars而不是函數範圍的本地)。如果從未調用dealloc,則塊將保留塊所有權對象。 「__weak」的目的實際上是爲了防止這種情況。 –