14

I niedawno natknąć Apple document który pokazuje następującą deklarację właściwości dla bloku:Definiowanie bloków Objective-C jak właściwości - najlepsze praktyki

@interface XYZObject : NSObject 
@property (copy) void (^blockProperty)(void); 
@end 

Ponadto, artykuł ten stwierdza:

Uwaga: Należy określić kopię jako atrybut właściwości, ponieważ blok musi zostać skopiowany, aby śledzić jego przechwycony stan poza zakresem oryginalnym. Nie jest to coś, o co musisz się martwić podczas korzystania z automatycznego liczenia odwołań, ponieważ dzieje się to automatycznie, ale najlepiej jest, gdy atrybut właściwości pokazuje wynikowe zachowanie. Aby uzyskać więcej informacji, zobacz Blogi - tematy programowania.

Przeczytałem również sugerowane Blocks Programming Topics, ale nie znalazłem tam niczego odpowiedniego.

Wciąż jestem ciekawy, dlaczego zdefiniowanie właściwości bloku jako "kopii" jest najlepszą praktyką. Jeśli masz dobrą odpowiedź, spróbuj rozróżnić różnice między ARC i MRC, jeśli takie istnieją.

Dziękujemy

+0

NB, dla początkujących, którzy zastanawiają się, jak do cholery użyć bloku :) http://stackoverflow.com/a/20760583/294884 – Fattie

Odpowiedz

23

Domyślnie bloki są tworzone na stosie. Znaczy to, że istnieją tylko w zakresie, w jakim zostały stworzone.

Jeśli chcesz uzyskać do nich dostęp później, muszą zostać skopiowane do stosu, wysyłając wiadomość copy do obiektu bloku. ARC zrobi to za Ciebie, gdy tylko wykryje, że blok musi być dostępny poza zakresem, w którym został utworzony. Najlepszą praktyką jest zadeklarowanie dowolnej właściwości bloku jako kopii, ponieważ tak powinno być w ramach automatycznego zarządzania pamięcią.

Przeczytaj Stack and Heap Objects in Objective-C Mike'a Ash, aby uzyskać więcej informacji na temat stosu a sterty.

+0

Dzięki za jasną odpowiedź, świetny link BTW – Stavash

+0

Nie powinny one być również zadeklarowane jako tydzień, na wypadek, gdybyś złapał własny i stworzył cykl zatrzymania? – cfischer

+0

Absolutnie nie, ponieważ przez większość czasu właściwość była jedynym odniesieniem do bloku, więc jeśli właściwość była słaba, blok znikłby natychmiast. – gnasher729

7

Bloki są domyślnie przydzielane na stosie. Jest to optymalizacja, ponieważ alokacja stosu jest znacznie tańsza niż alokacja sterty. Alokacja stosu oznacza, że ​​domyślnie blok przestanie istnieć, gdy zakres, w którym jest zadeklarowany, zostanie zakończony. Tak więc właściwość bloku z semantyką retain spowoduje zwisający wskaźnik do bloku, który już nie istnieje.

Aby przenieść blok ze stosu na stertę (a tym samym nadać mu normalną semantykę zarządzania pamięcią Celive-C i wydłużony czas życia), należy skopiować ten blok przez [theBlock copy], Block_copy(theBlock) itd. Raz na stercie, czas życia bloku można w razie potrzeby zarządzać, zachowując/zwalniając go. (Tak, dotyczy to w ARC też, po prostu nie mam zadzwonić -retain/-release siebie.)

Więc chcesz zadeklarować właściwości bloku z copy semantyki więc blok jest kopiowany, gdy właściwość jest ustawiona, unikając zwisający wskaźnik do bloku opartego na stosie.

+0

Jednak dwie powyższe odpowiedzi wydają się sugerować, że to musi być zrobione, a zresztą zrobione automatycznie, przez ARC - i ** jedyny powód ** do włączenia tej kopii wyraźnie jest stylistyczny - "przypomnieć wszystkim" to właśnie się dzieje. Myśli?? – Fattie

6

"Najlepsze praktyki", o których mówisz, mówią po prostu: "Widząc, że ARC zamierza magicznie skopiować twój blok, bez względu na to, co tutaj napiszesz, najlepiej napisać" kopiuj "tak, aby nie pomylić przyszłych pokoleń patrzących na Twój kod."

Wyjaśnienie następująco:

Zazwyczaj nie ma potrzeby, aby skopiować (lub utrzymać) blok. Kopię należy wykonać tylko wtedy, gdy oczekuje się, że blok zostanie użyty po zniszczeniu zakresu, w którym został zadeklarowany.Kopiowanie przenosi blok do sterty.
-Blokuje programowania Topics: z klocków, kopiowanie bloków

Oczywiście przypisanie blok właściwość oznacza, może być stosowany po zakres został zadeklarowanej została zniszczona. Tak więc, zgodnie z Blocks Programming Topics, ten blok powinien zostać skopiowany do sterty za pomocą Block_copy.

Ale ARC dba o to dla ciebie:

Blocks „po prostu działa” kiedy przechodzą bloki w górę stosu w trybie ARC, jak na przykład w zamian. Nie musisz już wywoływać funkcji Block Copy.
- Transitioning to ARC

Zauważ, że nie jest to o retain semantyki bloku. Po prostu nie ma możliwości, aby kontekst bloku istniał bez przeniesienia go ze stosu (wkrótce zostanie pobity) i do kupy. Niezależnie od tego, jakie atrybuty kwalifikujesz, ARC nadal będzie kopiować blok.

+0

W przypadku, gdy ktoś martwi się o wydajność lub funkcjonalność, po skopiowaniu bloku wynik jest niezmienny, a dalsze próby jego skopiowania zachowują go, podobnie jak inne niezmienne instancje. – gnasher729

+0

Cześć jenmore. Dzięki za post. Jak zapytałem powyżej, jaka jest twoja opinia ... "aby było absolutnie jasne, w rzeczywistości jest tak, że jeśli całkowicie pominiesz kopię, a nie kopię, faktycznie wynik, obsługa i wykonanie będą całkowicie identyczne? " Co sądzimy? Twoje zdrowie! – Fattie