Jaka jest różnica między słabym a blokowym odniesieniem?
Czytam dokumentację Xcode, a oto coś, co mnie zastanawia:
__block typeof(self) tmpSelf = self;
[self methodThatTakesABlock:^ {
[tmpSelf doSomething];
}];
Z dokumentacji skopiowano:
Blok tworzy silne odniesienie do zmiennych, które przechwytuje. W przypadku stosowania
self
w bloku blok tworzy silne odniesienie doself
, więc jeśliself
ma również silne odniesienie do bloku (który zazwyczaj robi), silne wyniki cyklu odniesienia. Aby uniknąć cyklu, potrzebujesz aby utworzyć słaby (lub__block
) odniesienie do siebie poza blokiem, jako w powyższym przykładzie.
Nie rozumiem co znaczy " słaby (lub __block
)"?
Jest
__block typeof(self) tmpSelf = self;
I
__weak typeof(self) tmpSelf = self;
Dokładnie to samo tutaj?
Znalazłem inny kawałek w dokumencie:
Uwaga: w środowisku śmieci, jeśli zastosujesz zarówno
__weak
, jak i__block
modyfikatory do zmiennej, wtedy blok nie zapewni, że zostanie utrzymany przy życiu.
Więc jestem całkowicie zdziwiony.
3 answers
From the docs about _ _ block
_ _ zmienne blokowe żyją w magazynie, który jest współdzielony między zakresem leksykalnym zmiennej a wszystkimi blokami i kopiami bloków zadeklarowanymi lub utworzonymi w zakresie leksykalnym zmiennej. Tak więc, magazyn przetrwa zniszczenie ramki stosu, jeśli jakiekolwiek kopie bloków zadeklarowanych w ramce przetrwają poza końcem ramki (na przykład przez zapytanie gdzieś do późniejszego wykonania). Wiele bloków w danym zakresie leksykalnym może jednocześnie używaj współdzielonej zmiennej.
From the docs about _ _ weak
__weak określa odniesienie, które nie utrzymuje obiektu odniesienia przy życiu. Słabe odniesienie jest ustawiane na nil, gdy nie ma silnych odniesień do obiektu.
Więc są to technicznie różne rzeczy. __block polega na zatrzymaniu kopiowania zmiennej z zewnętrznego zakresu do zakresu bloku. __weak jest samooddzielającym się słabym wskaźnikiem.
Uwaga powiedziałem technicznie, bo w Twoim przypadku zrobią (prawie) to samo. Jedyną różnicą jest to, czy używasz ARC, czy nie. Jeśli twój projekt używa ARC i jest tylko dla iOS4. 3 i nowszych, użyj _ _ weak. Zapewnia, że odniesienie jest ustawione na nil, jeśli globalne odniesienie do zakresu zostanie uwolnione. Jeśli twój projekt nie używa ARC lub jest przeznaczony dla starszych wersji systemu operacyjnego, użyj _ _ block.
Jest tu subtelna różnica, upewnij się, że ją rozumiesz.
EDIT: kolejny element układanki to _ _ unsafe_unrethed. To modyfikator jest prawie taki sam jak _ _ słaby, ale dla środowiska uruchomieniowego sprzed 4.3. Jednak nie jest ustawiony na zero i może pozostawić cię z wiszącymi wskaźnikami.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-02 08:25:26
W trybie ręcznego zliczania referencji, _ _ block id x; powoduje, że nie zachowuje x. w trybie łuku, __block id x; domyślnie zachowuje X (tak jak wszystkie inne wartości). Aby uzyskać zachowanie trybu ręcznego zliczania referencji pod Arc, możesz użyć _ _ unsafe_unrethed _ _ block id x;. Jak sugeruje nazwa _ _ unsafe_unrethed, jednak posiadanie zmiennej nie zatrzymanej jest niebezpieczne (ponieważ może zwisać) i dlatego jest zniechęcane. Dwie lepsze opcje to albo użycie _ _ słabe (jeśli nie musisz obsługiwać iOS 4 lub OS X v10.6) lub ustawić wartość _ _ block na nil, aby przerwać cykl zachowywania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-19 18:04:01
Oprócz innych odpowiedzi na _ _ blok vs _ _ słaby, istnieje inny sposób, aby uniknąć cyklu utrzymania w swoim scenariuszu.
@weakify(self);
[self methodThatTakesABlock:^ {
@strongify(self);
[self doSomething];
}];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-26 08:58:22