W kodzie z włączoną funkcją ARC, jak naprawić ostrzeżenie o potencjalnym cyklu przechowywania podczas korzystania z interfejsu API opartego na blokach?
Ostrzeżenie:
Capturing 'request' strongly in this block is likely to lead to a retain cycle
utworzony przez ten fragment kodu:
ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:...
[request setCompletionBlock:^{
NSDictionary *jsonDictionary = [[CJSONDeserializer deserializer] deserialize:request.rawResponseData error:nil];
// ...
}];
Ostrzeżenie jest powiązane z użyciem obiektu request
wewnątrz bloku.
responseData
zamiastrawResponseData
, sprawdź dokumentację ASIHTTPRequest.Odpowiedzi:
Odpowiadam sobie:
Z mojego rozumienia dokumentacji wynika, że użycie słowa kluczowego
block
i ustawienie zmiennej na zero po użyciu go w bloku powinno być w porządku, ale nadal wyświetla ostrzeżenie.Aktualizacja: sprawiłem, że działa ze słowem kluczowym „_ słaby” zamiast „ _block” i używając zmiennej tymczasowej:
Jeśli chcesz również kierować reklamy na iOS 4, użyj
__unsafe_unretained
zamiast__weak
. To samo zachowanie, ale wskaźnik pozostaje zawieszony zamiast być automatycznie ustawiany na zero, gdy obiekt zostanie zniszczony.źródło
Ten problem występuje, ponieważ przypisujesz blok do żądania, który ma silne odniesienie do żądania. Blok automatycznie zachowa żądanie, więc pierwotne żądanie nie zostanie zwolnione z powodu cyklu. Ma sens?
To po prostu dziwne, ponieważ tagujesz obiekt żądania za pomocą __block, aby mógł odwoływać się do siebie. Możesz to naprawić, tworząc obok niego słabe odniesienie .
źródło
Powoduje to poprzez zatrzymanie siebie w bloku. Blok będzie dostępny od siebie, a do siebie odnosi się blok. stworzy to cykl utrzymania.
Spróbuj rozwiązać ten problem, tworząc słabe odniesienie do
self
źródło
Czasami kompilator xcode ma problemy z identyfikatorem zachowań cykli, więc jeśli jesteś pewien, że nie zachowujesz kompletnego elementu, możesz umieścić flagę kompilatora w następujący sposób:
źródło
Kiedy wypróbowuję rozwiązanie dostarczone przez Guillaume, wszystko jest w porządku w trybie debugowania, ale ulega awarii w trybie wydania.
Zauważ, że nie używaj __weak, ale __unsafe_unretained, ponieważ moim celem jest iOS 4.3.
Mój kod ulega awarii, gdy setCompletionBlock: jest wywoływana na obiekcie „request”: żądanie zostało cofnięte ...
Tak więc to rozwiązanie działa zarówno w trybie debugowania, jak i wydania:
źródło
jaka jest różnica między odwołaniem __weak a __block?
źródło
Zapoznaj się z dokumentacją w witrynie programistów Apple: https://developer.apple.com/library/prerelease/ios/#documentation/General/Conceptual/ARCProgrammingGuide/Introduction.html#//apple_ref/doc/uid/TP40011029
U dołu strony znajduje się sekcja dotycząca zachowywania cykli.
źródło