2013-07-24 13 views
6

Rozumiem, że typ pamięci __block jest potrzebny dla zmiennych skalarnych dla bloku, aby zobaczyć aktualizacje do nich, ale kiedy jest to potrzebne dla obiektów? Uważam, że należy używać __weak podczas przechwytywania własnego odwołania do użycia w bloku, ale nie widzę, kiedy byłoby konieczne używanie typu przechowywania __block dla zwykłych obiektów.Kiedy używać słowa kluczowego __block do odwołań do obiektów z ARC

+0

Również [jaka jest różnica między __weak i __block referencja?] (http://stackoverflow.com/questions/11773342/what-the-difference-between-weak-and-block-reference) –

+0

Pytam konkretnie: kiedy typ pamięci "__block" sh czy przy użyciu ARC można używać odwołań nieskalarnych, nieautomatycznych? Jeśli te inne linki odpowiadają na to pytanie, przegapiłem to. – chinabuffet

+0

@ chinabuffet: Nie ma różnicy między tym, jak to działa dla typów skalarnych i typów wskaźników obiektów. – newacct

Odpowiedz

15

__block jest potrzebny dla zmiennych skalarnych, jeśli chcesz zmienić ich wartość za pomocą kodu wewnątrz bloku. Przechwycone skalary pojawiają się wewnątrz bloku i dlatego nie można ich zmienić. Jeśli masz wskaźnik do obiektu, obowiązuje to samo rozróżnienie - przechwycony wskaźnik sam w sobie będzie wskaźnikiem const i dlatego nie może być modyfikowany, ale wskazywany obiekt może być modyfikowany kodem wewnątrz bloku. Jeśli chcesz zmienić wskazany obiekt, sam wskaźnik musi się zmienić, a więc wskaźnik musi zostać zadeklarowany za pomocą typu __block. Nigdy nie jest konieczne deklarowanie samego obiektu jako __block, ale tylko wskaźnik do obiektu i tylko wtedy, gdy wskaźnik musi zostać zmieniony.

Jeśli masz właściwy model mentalny, bloki nie są tak mylące. Ważne jest, aby wiedzieć, że bloki są początkowo przydzielane na stosie, a więc znikają, gdy zakres leksykalny zostanie zniszczony, gdy klatka stosu zostanie wysunięta. Jeśli chcesz, aby blok się zawiesił po okresie obowiązywania zakresu leksykalnego, w którym blok został utworzony, przenieś go do sterty za pomocą Block_copy() lub wyślij wiadomość o numerze -copy. Kiedy blok jest kopiowany do sterty, wszystkie przechwycone zmienne przechodzą dalej, a wszelkie obiekty, które te zmienne wskazują, są zachowywane. Po usunięciu bloku ze sterty wszystkie obiekty wskazywane przez zmienne const są zwalniane.

__block zmienne „pod maską” ma dodatkową warstwę zadnie zastosowań kompilatora (i że nie widać) wchodzące w skład bloku, więc gdy blok jest kopiowany do sterty, więc są przechwytywane __block zmienne , a niewidoczne wskaźniki są dostosowane tak, aby wskazywały na nową lokalizację sterty tych zmiennych __block. Oznacza to, że adres zmiennej __block może ulec zmianie, więc zachowaj ostrożność, jeśli użyjesz tego adresu. Można również zauważyć, że zmienna __block żyje w pewnym sensie "poza" blokiem, więc te zmienne można odczytać i zmodyfikować z kodu zewnętrznego do bloku.

byłem krótko, ale można znaleźć lepsze wyjaśnień tutaj, wymienione w rosnącej złożoności:

http://ios-blog.co.uk/tutorials/programming-with-blocks-an-overview/

http://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html

http://www.mikeash.com/pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html

+0

Więc jeśli blok jest przekazywany gdzieś jako odniesienie, czy cokolwiek otrzymuje ten blok jako parametr, musi natychmiast skopiować blok, aby móc go użyć w przyszłości? – chinabuffet

+0

Jeśli odwołanie do bloku może przekroczyć zasięg leksykalny (ramkę stosu), w którym zdefiniowano blok, musi zostać skopiowane, aby przenieść obiekt blokowy do sterty. Wydaje mi się, że bezpieczniej byłoby wykonać kopię podczas tworzenia bloku, niż gdyby kopie miały miejsce w miejscach odległych od kreacji. – Fred

0

Są one używane do zmiennych poziomu funkcji. Są one zmienne wewnątrz bloku (i otaczającego zakresu) i są zachowywane, jeśli dowolny blok referencji jest kopiowany do sterty. Zmienne lokalne do otaczającego zakresu leksykalnego zadeklarowanego za pomocą modyfikatora pamięci __block są dostarczane przez odniesienie i dlatego są zmienne. Wszelkie zmiany znajdują odzwierciedlenie w otaczającym zakresie leksykalnym, w tym w innych blokach zdefiniowanych w tym samym rozszerzającym się zakresie leksykalnym.

__block zmienne znajdują się w pamięci masowej podzielonej między zakres leksykalny zmiennej oraz wszystkie bloki i kopie blokowe zadeklarowane lub utworzone w zakresie leksykalnym zmiennej. W ten sposób pamięć przetrwa zniszczenie ramki stosu, jeśli dowolne kopie bloków zadeklarowanych w ramce przetrwają poza końcem klatki (na przykład, gdy są zakolem gdzieś w celu późniejszego wykonania). Więc używaj ich, gdy potrzebujesz zmodyfikować obiekt w bloku lub gdy będziesz potrzebował obiektu po zniszczeniu ramki stosu.

Powiązane problemy