Podstawowym problemem związanym z pamięcią, o którym wciąż musisz wiedzieć, jest zachowanie cykli. Dzieje się tak, gdy jeden obiekt ma silny wskaźnik do drugiego, ale obiekt docelowy ma silny wskaźnik z powrotem do oryginału. Nawet jeśli wszystkie inne odniesienia do tych obiektów zostaną usunięte, nadal będą się one trzymać i nie zostaną zwolnione. Może się to również zdarzyć pośrednio, przez łańcuch obiektów, który może mieć ostatni w łańcuchu odwołujący się do wcześniejszego obiektu.
Z tego powodu istnieją kwalifikatory __unsafe_unretained
i __weak
własność. Ten pierwszy nie zatrzyma żadnego obiektu, na który wskazuje, ale pozostawia otwartą możliwość, że ten obiekt zniknie i będzie wskazywał na złą pamięć, podczas gdy drugi nie zatrzyma obiektu i automatycznie ustawi się na zero, gdy jego cel zostanie zwolniony. Z tych dwóch __weak
jest ogólnie preferowany na platformach, które go obsługują.
Używałbyś tych kwalifikatorów do takich rzeczy jak delegaci, w których nie chcesz, aby obiekt zachował swoją delegację i potencjalnie doprowadził do cyklu.
Kolejną istotną kwestią związaną z pamięcią jest obsługa obiektów Core Foundation i pamięci przydzielanej przy użyciu malloc()
takich typów char*
. ARC nie zarządza tymi typami, tylko obiektami Objective-C, więc nadal będziesz musiał sobie z nimi poradzić. Typy Core Foundation mogą być szczególnie trudne, ponieważ czasami trzeba je połączyć w celu dopasowania do obiektów Objective-C i odwrotnie. Oznacza to, że kontrola musi być przenoszona w tę iz powrotem z ARC podczas mostkowania między typami CF i Objective-C. Dodano niektóre słowa kluczowe związane z tym mostowaniem, a Mike Ash ma świetny opis różnych przypadków mostkowania w swoim długim opisie ARC .
Oprócz tego istnieje kilka innych rzadszych, ale wciąż potencjalnie problematycznych przypadków, które szczegółowo opisano w opublikowanej specyfikacji .
Wiele z nowych zachowań, opartych na utrzymywaniu obiektów tak długo, jak długo jest do nich silny wskaźnik, jest bardzo podobne do wyrzucania elementów bezużytecznych na komputerze Mac. Podstawy techniczne są jednak bardzo różne. Ten styl zarządzania pamięcią opiera się na sztywnych zasadach zatrzymywania / zwalniania, których wszyscy musimy przestrzegać w Objective-C, zamiast procesu śmieciarza, który działa w regularnych odstępach czasu w celu czyszczenia obiektów, o których nie ma już mowy.
ARC po prostu przenosi powtarzające się zadania zarządzania pamięcią, które musieliśmy wykonywać od lat, i przenosi je do kompilatora, abyśmy nigdy więcej nie musieli się o nie martwić. W ten sposób nie występują problemy z zatrzymywaniem ani profile pamięci piłokształtnych występujące na platformach odśmiecania. Doświadczyłem obu tych rzeczy w moich śmieciowych aplikacjach Mac i chętnie sprawdzam, jak zachowują się pod ARC.
Aby uzyskać więcej informacji na temat wyrzucania elementów bezużytecznych w porównaniu do ARC, zobacz tę bardzo interesującą odpowiedź Chrisa Lattnera na liście mailingowej Objective-C , w której wymieniono wiele zalet ARC w porównaniu do odśmiecania Objective-C 2.0. Natknąłem się na kilka problemów GC, które opisuje.
ARC nie pomoże ci z pamięcią inną niż ObjC, na przykład jeśli
malloc()
coś, nadal musisz tegofree()
zrobić.ARC można oszukać,
performSelector:
jeśli kompilator nie może dowiedzieć się, co to jest selektor (kompilator wygeneruje ostrzeżenie o tym).ARC będzie również generować kod zgodnie z konwencjami nazewnictwa ObjC, więc jeśli wymieszasz kod ARC i MRC, możesz uzyskać zaskakujące wyniki, jeśli kod MRC nie spełni oczekiwań kompilatora.
źródło
W mojej aplikacji wystąpiły wycieki pamięci z powodu następujących 4 problemów:
Na szczęście natknąłem się na następujący post na blogu i byłem w stanie je poprawić: http://www.reigndesign.com/blog/debugging-retain-cycles-in-objective-c-four-likely-culprits/
źródło
ARC nie będzie również zarządzać typami CoreFoundation. Możesz je „zmostkować” (za pomocą
CFBridgingRelease()
), ale tylko wtedy, gdy zamierzasz użyć go jako obiektu Objective-C / Cocoa. Zauważ, że CFBridgingRelease po prostu zmniejsza licznik zatrzymania CoreFoundation o 1 i przenosi go do ARC Celu-C.źródło
Xcode 9 stanowi doskonałe narzędzie do znajdowania tego rodzaju problemów. Nazywa się to: „ Debuguj wykres pamięci ”. Używając go, możesz znaleźć wyciekający obiekt według typu klasy i możesz wyraźnie zobaczyć, kto ma do niego silne odniesienie, zwolnienie go stamtąd rozwiązuje twój problem. Wykrywa również cykle pamięci.
Zobacz więcej informacji o tym, jak go używać
źródło