9

Mam kod z wyraźnym cyklem odniesienia w bloku ivar. Poniższy kod powoduje cyklu odniesienia i dealloc nigdy nie nazywa się:__blokuj własny cykl odniesienia w bloku ivar w ARC

__block MyViewController *blockSelf = self; 

loggedInCallback = ^(BOOL success, NSError *error){ 
    if (success) 
    { 
     double delayInSeconds = 1.0; 
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
     dispatch_after(popTime, dispatch_get_main_queue(), ^(void) 
     { 
      [blockSelf.delegate loginDidFinish]; 
     });    
    } 
}; 

Jednakże, jeśli tworzę innej zmiennej __block posiadać odniesienie do mojego delegata do zakresu stosowania bloku do przechwytywania, cykl odniesienia odchodzi:

__block id <MyViewControllerDelegate> blockDelegate = self.delegate; 

loggedInCallback = ^(BOOL success, NSError *error){ 
    if (success) 
    { 
     double delayInSeconds = 1.0; 
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
     dispatch_after(popTime, dispatch_get_main_queue(), ^(void) 
     { 
      [blockDelegate loginDidFinish]; 
     });    
    } 
}; 

Chcę tylko zrozumieć, co się tutaj dzieje.

Odpowiedz

16

Zamierzam założyć, że używasz ARC tutaj. Przed ARC Twój pierwszy przykład działałby dobrze. W ARC zmieniła się semantyka __block. __block deklaracje są teraz silnie przechwytywane, a nie słabe. Wymień __block na __weak w pierwszej próbce i wszystkie powinny działać zgodnie z oczekiwaniami.

Co do działania drugiego przykładu, tworzysz silne odniesienie do delegata, ale twoje, które nie ma odniesienia do twojego obiektu. Tak więc żaden cykl i wszyscy są szczęśliwi.

Polecam przeczytaniu artykułu Mike'a Asha o zmianach wprowadzonych z ARC, zwłaszcza wokół bloku przechwytywania i __weakhttp://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html

+0

Perfect, dzięki! Zaktualizowałem tytuł mojego pytania, by był bardziej opisowy. –

+1

Jestem kierowany na system iOS 4.3, więc zamiast tego użyłem '' __unsafe_unretained'', ale działa, dziękuję! –