Wiem, że blok Objective-C może przechwytywać i ustawiać wartość zmiennych poza zakresem obejmującym. Jak to robi?W jaki sposób blok przechwytuje zmienne poza zakresem obejmującym?
Odpowiedz
W treści kodu obiektu blokowego zmienne można traktować na pięć różnych sposobów.
Można odwołać trzy standardowe typy zmiennych, tak samo jak z funkcji:
- zmiennych globalnych, w tym mieszkańców statycznych
- globalne funkcje (które nie są technicznie zmienne)
- lokalny zmienne i parametry z obejmującego zakresu
Bloki obsługują również dwa inne typy zmiennych:
Na poziomie funkcji są zmienne
__block
. Są one zmienne wewnątrz bloku (i otaczającego zakresu) i są zachowywane, jeśli dowolny blok referencji jest kopiowany do sterty.
const
import.Wreszcie, w ramach implementacji metody, bloki mogą odwoływać się do zmiennych instancji Objective-C - patrz zmienne Object i Block.
Poniższe zasady odnoszą się do zmiennych wykorzystywanych w bloku:
zmienne globalne są dostępne, w tym zmiennych statycznych, które istnieją w otaczającej zakresu leksykalnego.
Parametry przekazywane do bloku są dostępne (podobnie jak parametry do funkcji).
Zmienne stosu (niestatyczne) lokalne do otaczającego zakresu leksykalnego przechwytywane są jako zmienne
const
.Ich wartości są pobierane w punkcie wyrażenia bloku w programie. W zagnieżdżonych blokach wartość jest przechwytywana z najbliższego otaczającego zakresu.
Zmienne lokalne do otaczającego zakresu leksykalnego zadeklarowanego za pomocą modyfikatora pamięci
__block
są dostarczane przez odniesienie i dlatego można je zmieniać.Wszelkie zmiany znajdują odzwierciedlenie w otaczającym zakresie leksykalnym, w tym w innych blokach zdefiniowanych w tym samym rozszerzającym się zakresie leksykalnym. Zostały one omówione bardziej szczegółowo w The __block Storage Type.
Zmienne lokalne zadeklarowane w zakresie leksykalnym bloku, które zachowują się dokładnie tak jak zmienne lokalne w funkcji.
Każde wywołanie bloku dostarcza nową kopię tej zmiennej. Te zmienne mogą z kolei być użyte jako zmienne referencyjne w blokach zamkniętych w bloku.
I jeszcze jeden ... zmienne instancji, o których mowa do wewnątrz zakresu bloku oznacza silne odniesienie do 'self', a zmienne instancji będą odzwierciedlać wartość obecną w momencie wykonywania bloku. Co może być mylące. – bbum
Pytanie z pytaniem, w jaki sposób bloki są w stanie przechwytywać zmienne. Nie semantyka przechwytywania zmiennych. – newacct
To rzeczywiście dość proste i opisane w Clang w Bloku Wdrażania Spec, w sekcji "Imported Variables".
Gdy kompilator napotka bloku jak:
^{ if(numBalloons > numClowns) abort(); }
tworzy dosłownego strukturę, która zawiera - między innymi - dwa elementy, które są tu ważne. W bloku znajduje się wskaźnik funkcji do kodu wykonywalnego oraz pole const
dla każdej zmiennej, do której odwołuje się wewnątrz bloku. Coś takiego:
struct __block_literal_1 {
/* other fields */
void (*invoke)(struct __block_literal_1 *);
/* ... */
const int numBalloons;
const int numClowns;
};
Zauważ, że funkcja invoke
odbędzie wskaźnik do struktury tego rodzaju, że zdefiniowana jest tutaj; to znaczy, Blok przechodzi sam podczas wykonywania swojego kodu. W ten sposób kod uzyskuje dostęp do członków struktury.
Zaraz po zgłoszeniu, kompilator tworzy definicję bloku, który po prostu korzysta z odwołują zmienne zainicjować odpowiednie pola w struct
:
struct __block_literal_1 __block_literal_1 = {
/* Other fields */
__block_invoke_2, /* This function was also created by the compiler. */
/* ... */
numBalloons, /* These two are the exact same variables as */
numClowns /* those referred to in the Block literal that you wrote. *
};
Następnie wewnątrz funkcji invoke
odniesienia do przechwycone zmienne są tworzone jak każdy inny element struktury, the_block->numBalloons
.
Sytuacja dla zmiennych typu obiektowego jest nieco bardziej skomplikowana, ale obowiązuje ta sama zasada.
Zasadniczo, blok "obiekt" zawiera zmienną wewnątrz obiektu bloku (jak "zmienna instancji" obiektu bloku) dla każdej wychwyconej zmiennej lokalnej. (Odpowiedź Josha Caswella dostarcza więcej szczegółów na temat sposobu jego implementacji.) Po utworzeniu bloku wartość każdej wychwyconej zmiennej lokalnej w tym czasie jest kopiowana do odpowiedniej zmiennej wewnątrz bloku. Ilekroć zmienna jest używana wewnątrz bloku, używa ona tej zmiennej wewnątrz bloku.
- 1. Objective-C: zmienne instancji poza zakresem w debugerze
- 2. Enum zadeklarowany poza zakresem klasy
- 3. Python - "indeks krotek poza zakresem"
- 4. Unsigned Long Long poza zakresem?
- 5. IndexError: indeks poza zakresem: 7
- 6. Zapobieganie Index Poza zakresem błędu
- 7. java.sql.SQLException wskaźnik Parametr poza zakresem
- 8. AngularUI Datepicker wyłącz daty poza zakresem
- 9. PRAWDZIWE wartości trzymania kolumny poza udokumentowanym zakresem
- 10. W jaki sposób Screentoaster.com przechwytuje ekran komputera z przeglądarki?
- 11. W jaki sposób przechwytuje mysz ComboBox po jej opuszczeniu?
- 12. Dlaczego lambda przechwytuje tylko zmienne automatyczne?
- 13. W jaki sposób PHP obsługuje zmienne?
- 14. wywołanie funkcji javascript poza zakresem ng-click
- 15. Wyjątek wyrzucania, gdy tablica jest poza zakresem
- 16. findspark.init() IndexError: indeks listy poza zakresem błędu
- 17. Jak zmienić dane AngularJS poza zakresem?
- 18. trzpień nltk: indeks ciągów poza zakresem
- 19. java.lang.IllegalArgumentException: pointerIndex poza zakresem Wyjątek - dispatchTouchEvent
- 20. Dostęp do zmiennej poza zakresem funkcji
- 21. std :: unordered_map wektor indeksu poza zakresem
- 22. Podłańcuch języka Java: 'indeks ciągu poza zakresem'
- 23. Główna Błąd: lista indeks poza zakresem (Python)
- 24. Numer Mysql int (11) poza zakresem
- 25. Czy Julia obsługuje zmienne statyczne z zakresem funkcji
- 26. W jaki sposób kompilator wie, który blok catch ma wykonać?
- 27. Jest wreszcie "poza zakresem" w bloku prób/catch
- 28. Jak zapisać globalne zmienne w programie iOS?
- 29. W jaki sposób zmienne są przechowywane w pamięci w rekursji?
- 30. C w/bloków: bloki na stosie będzie poza zakresem
Myślę, że w zasadzie traktuje to tak, jakby zmienne zewnętrzne nie wykraczały poza zakres, gdy zakres został zdefiniowany w końcach, używał bloków dużo, ale nie mógłbym się liczyć jako ekspert – Fonix