2013-06-29 12 views
6

Przeczytałem dokumentację na __block variables i zastanawiając się nad przypadkami, w których używam __block. Dla mnie wydaje się, że muszę go w dwóch przypadkach:Dlaczego zmienne __block nie są zachowywane (w środowiskach innych niż ARC)?

  • aby zaznaczyć zmienną do odczytu zapisu stosowany w bloku
  • aby uniknąć zatrzymywania cykli po przedstawieniu siebie w bloku

Na powierzchni nie wydaje się, że te dwie rzeczy są ze sobą powiązane. Uważam, że zmienne __block nie są zachowywane jako więcej podstępu, który muszę zapamiętać w konkretnym przypadku unikania cykli zatrzymania.

Zastanawiam się, czy istnieje ważniejszy, architektoniczny powód, dla którego nie wolno ich zatrzymać? Sądzę, że inne słowo kluczowe wskazuje, że może to być bardziej jasne, ponieważ nie miesza dwóch wyżej wymienionych funkcji.

update -

należy wspomnieć, jest to kod, który nie korzysta z ARC. Teraz widzę, że zmienne __block są w rzeczywistości zachowywane w ARC.

+2

Używa się tylko '__block' dla pierwszego. Używasz '__weak', a nie' __block', aby uniknąć cykli zatrzymania. – rmaddy

+2

Ponadto, skąd wziął się pomysł, że zmienne __block nie są zachowywane? ARC zatrzyma je automatycznie, podobnie jak zwykłe zmienne. –

+2

Przed ARC, zmienne __block nie zostały faktycznie zachowane jako mechanizm unikania cykli zatrzymania. To się zmieniło w ARC i jest udokumentowane w Uwagach do Przejścia do ARC. –

Odpowiedz

12

__block zmienne nie zostaną zachowane, jeśli używasz ręcznego liczenia odwołań. Powodem można znaleźć tutaj: http://www.mikeash.com/pyblog/friday-qa-2009-08-14-practical-blocks.html:

proste obejście tego jest fakt, że __block zmienne nie są zachowywane. Dzieje się tak dlatego, że takie zmienne są zmienne, a automatyczne zarządzanie nimi wymaga, aby każda mutacja generowała kod zarządzania pamięcią za kulisami. Było to postrzegane jako zbyt intruzywne i trudne do uzyskania, zwłaszcza, że ​​ten sam blok może być wykonywany jednocześnie z wielu wątków.

i również tutaj: http://lists.apple.com/archives/objc-language/2009/Dec/msg00100.html

Nie ma sposobu, aby poprawnie i efektywnie zarządzać zachowują liczy po ponownym przypisaniem wartości w zmiennej.

(. Nie mogłem znaleźć „oficjalne” odniesienie w dokumentacji firmy Apple)

Jak udokumentowano w "Transitioning to ARC Release Notes" to zachowanie zmienić za pomocą łuku:

W trybie ręcznego liczenia odniesienia, __block id x; ma wpływ nie zachowując x. W trybie ARC domyślnie __block id x; zachowuje x (tylko , podobnie jak wszystkie inne wartości). Aby uzyskać ręczny tryb liczenia odniesień zachowanie w ramach ARC, można użyć __unsafe_unretained __block id x;. Jak sugeruje nazwa __unsafe_unretained, posiadanie niepobranej zmiennej jest niebezpieczne (ponieważ może zwisać) i dlatego jest zniechęcane . Dwiema lepszymi opcjami są: użycie __weak (jeśli nie potrzebujesz obsługi iOS 4 lub OS X v10.6), lub ustaw wartość __block na nil, aby przerwać cykl zachowywania.

+0

Miło, to ma sens. Dzięki. –

+0

@darren: Po ponownym przeczytaniu tych odniesień, wydaje mi się, że unikanie cykli zatrzymania jest bardziej efektem ubocznym niż celem projektu zmiennych __block. –

Powiązane problemy