Dlaczego delegaci Objective-C zazwyczaj otrzymują przypisanie własności zamiast zachowywania?

Przeglądam wspaniały blog prowadzony przez Scotta Stevensona i staram się zrozumieć fundamentalną koncepcję Objective-C przypisywania delegatom własności "przypisać" vs "zachować". Zauważ, że oba są takie same w środowisku śmieci. Głównie zajmuję się środowiskiem opartym na GC (np.

Prosto z bloga Scotta:

" słowo kluczowe assign wygeneruje setter, który przypisuje wartość zmiennej instancji bezpośrednio, a nie kopiowanie lub zachowywanie go. Jest to najlepsze dla prymitywnych typów, takich jak NSInteger i CGFloat, lub obiektów, których bezpośrednio nie posiadasz, takich jak delegaty."

Co to znaczy, że nie posiadasz bezpośrednio obiektu delegata? Zazwyczaj Zatrzymuję swoich delegatów, ponieważ jeśli nie chcę, aby odeszli w otchłań, zachowam to za mnie. Zwykle abstrakcyjny UITableViewController z dala od odpowiedniego źródła danych i delegata również. Zatrzymuję również ten konkretny przedmiot. Chcę zrobić jasne, że nigdy nie odchodzi, więc mój UITableView zawsze ma swojego delegata w pobliżu.

Może ktoś jeszcze wyjaśnić gdzie/dlaczego się mylę, żebym mógł zrozumieć ten wspólny paradygmat programowania Objective-C 2.0 polegający na używaniu właściwości assign na delegatach zamiast zachowywania?

Dzięki!

Author: Plumenator, 2009-05-28

4 answers

Powodem, dla którego unikasz zatrzymywania delegatów, jest to, że musisz unikać cyklu zatrzymywania:

A tworzy B A ustawia się jako delegat B … A jest zwolniony przez jego właściciela

Gdyby B zachował A, A nie zostałby zwolniony, ponieważ B posiada a, więc dealloc A nigdy nie zostałby wywołany, powodując wyciek ZARÓWNO A, jak i B .

Nie powinieneś martwić się o odejście A, ponieważ posiada B i tym samym pozbawia się go w dealloc.

 175
Author: Andrew Pouliot,
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
2015-05-10 22:25:00

Ponieważ obiekt wysyłający wiadomości delegata nie jest jego właścicielem.

Wiele razy jest odwrotnie, jak w przypadku, gdy kontroler ustawia się jako delegat widoku lub okna: kontroler jest właścicielem widoku / okna, więc jeśli Widok / okno posiada swojego delegata, oba obiekty byłyby właścicielami siebie nawzajem. Jest to oczywiście cykl zachowawczy, podobny do wycieku z tą samą konsekwencją (obiekty, które powinny być martwe, pozostają żywe).

Innym razem, obiekty są rówieśnikami: żaden z nich nie jest właścicielem drugiego, prawdopodobnie dlatego, że oba są własnością tego samego trzeciego obiektu.

Tak czy inaczej, obiekt z delegatem nie powinien zachować swojego delegata.

(jest przynajmniej jeden wyjątek, nawiasem mówiąc. Nie pamiętam, co to było i nie sądzę, żeby był ku temu dobry powód.)


Dodatek (dodano 2012-05-19): w polu ARC należy użyć weak zamiast assign. Słabe odwołania są ustawiane na nil automatycznie, gdy obiekt umiera, wyeliminowanie możliwości, że obiekt delegujący będzie wysyłać wiadomości do martwego delegata.

Jeśli z jakiegoś powodu trzymasz się z dala od ARC, Zmień przynajmniej właściwości assign, które wskazują na obiekty na unsafe_unretained, które wyraźnie wskazują, że jest to nieuregulowane, ale nie zerujące odniesienie do obiektu.

assign pozostaje odpowiedni dla wartości innych niż obiekt zarówno pod ARC, jak i MRC.

 44
Author: Peter Hosey,
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-05-19 09:04:07

Zauważ, że gdy masz przypisanego delegata, bardzo ważne jest, aby zawsze ustawiać wartość tego delegata na nil, gdy obiekt ma być deallocowany - więc obiekt powinien zawsze uważać, aby nie usuwać odwołań do delegatów w dealloc, jeśli nie zrobił tego gdzie indziej.

 17
Author: Kendall Helmstetter Gelner,
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
2009-05-28 15:17:46

Jednym z powodów tego jest unikanie zatrzymywania cykli. Aby uniknąć sytuacji, w której A i B oba obiekty odwołują się do siebie i żaden z nich nie jest zwolniony z pamięci.

Acutally assign jest najlepszy dla prymitywnych typów, takich jak NSInteger i CGFloat, lub obiektów, których bezpośrednio nie posiadasz, takich jak delegaty.

 1
Author: Puneet Sharma,
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
2015-12-28 10:01:51