Chciałbym wiedzieć, z jakiej sytuacji korzystałeś do -retainCount
tej pory, a ostatecznie jakie problemy mogą się zdarzyć przy jego użyciu.
Dzięki.
Chciałbym wiedzieć, z jakiej sytuacji korzystałeś do -retainCount
tej pory, a ostatecznie jakie problemy mogą się zdarzyć przy jego użyciu.
Dzięki.
Odpowiedzi:
Nigdy nie powinieneś używać -retainCount
, ponieważ nigdy nie mówi ci nic przydatnego. Wdrożenie frameworków Foundation i AppKit / UIKit jest nieprzejrzyste; nie wiesz, co jest zatrzymywane, dlaczego to jest zatrzymywane, kto to zachowuje, kiedy zostało zachowane i tak dalej.
Na przykład:
[NSNumber numberWithInt:1]
miałoby toretainCount
1. Nie. Jest 2.@"Foo"
będzie równe retainCount
1. Nie. Jest to 1152921504606846975.[NSString stringWithString:@"Foo"]
będzie równe retainCount
1. Nie. Ponownie jest to 1152921504606846975.Zasadniczo, ponieważ wszystko może zachować obiekt (a tym samym zmienić jego retainCount
), a ponieważ nie masz źródła większości kodu, który uruchamia aplikację, obiekt retainCount
jest bez znaczenia.
Jeśli próbujesz wyśledzić, dlaczego obiekt nie jest zwalniany, użyj narzędzia Wycieki w Instrumentach. Jeśli próbujesz ustalić, dlaczego obiekt został zwolniony zbyt wcześnie, użyj narzędzia Zombie w Instrumentach.
Ale nie używaj -retainCount
. To naprawdę bezwartościowa metoda.
edytować
Proszę, wszyscy wejdź na http://bugreport.apple.com i poproś o -retainCount
wycofanie. Im więcej osób o to prosi, tym lepiej.
edytuj # 2
W ramach aktualizacji [NSNumber numberWithInt:1]
ma teraz retainCount
numer 9223372036854775807. Jeśli Twój kod oczekiwał, że będzie to 2, Twój kod jest teraz uszkodzony.
- (NSUInteger)retainCount{return NSUIntegerMax;}
.
retainCount
.
Poważnie. Po prostu tego nie rób.
Wystarczy postępować zgodnie z Wytyczne zarządzanie pamięcią i tylko zwolnić co alloc
, new
lub copy
(lub cokolwiek nazywane retain
po pierwotnie).
@bbum powiedział to najlepiej tutaj na SO , a jeszcze bardziej szczegółowo na swoim blogu .
-retainCount
można uzyskać (o wiele bardziej szczegółowo) z Instruments i jego narzędzi.
retain
, retain
, retain
, autorelease,
autorelease, autorelease
może być całkowicie poprawny wynik przekazywania obiektu przez API UIKit, na przykład.
Obiekty zwolnione automatycznie są jednym z przypadków, w których sprawdzenie -retainCount jest nieinformacyjne i może wprowadzać w błąd. Licznik retainy nie mówi nic o tym, ile razy -autorelease zostało wywołanych na obiekcie, a zatem ile razy zostanie on zwolniony, gdy bieżąca pula autowydzielania zostanie wyczerpana.
Uważam , że retainCounts jest bardzo przydatne podczas sprawdzania za pomocą „Instrumentów”.
Korzystając z narzędzia „alokacje”, upewnij się, że opcja „Rekord liczników odwołań” jest włączona i możesz przejść do dowolnego obiektu i zobaczyć jego historię retainCount.
Łącząc alokacje i wydania, możesz uzyskać dobry obraz tego, co się dzieje i często rozwiązywać trudne przypadki, w których coś nie jest publikowane.
To nigdy mnie nie zawiodło - w tym znajdowanie błędów we wczesnych wersjach beta iOS.
Spójrz na dokumentację Apple na temat NSObject, prawie obejmuje ona twoje pytanie: NSObject retainCount
Krótko mówiąc, retainCount jest prawdopodobnie bezużyteczne, chyba że zaimplementowałeś własny system liczenia referencji (i mogę prawie zagwarantować, że nie będziesz go mieć).
Według własnych słów Apple, retainCount „zwykle nie ma wartości w debugowaniu problemów z zarządzaniem pamięcią”.
Oczywiście nigdy nie powinieneś używać metody retainCount w swoim kodzie, ponieważ znaczenie jej wartości zależy od tego, ile autowydzierżawień zostało zastosowanych do obiektu, a tego nie możesz przewidzieć. Jest to jednak bardzo przydatne do debugowania - szczególnie podczas wyszukiwania wycieków pamięci w kodzie, który wywołuje metody obiektów Appkit poza główną pętlą zdarzeń - i nie powinno być przestarzałe.
Starając się przedstawić swój punkt widzenia, poważnie przeceniliście niezbadany charakter wartości. Prawdą jest, że nie zawsze jest to liczba referencyjna. Istnieją pewne specjalne wartości używane dla flag, na przykład w celu wskazania, że obiekt nie powinien być nigdy zwalniany. Liczba taka jak 1152921504606846975 wygląda bardzo tajemniczo, dopóki nie napiszesz jej szesnastkowo i nie otrzymasz 0xfffffffffffffff. A 9223372036854775807 to 0x7fffffffffffffff w zapisie szesnastkowym. I naprawdę nie jest tak zaskakujące, że ktoś zdecydowałby się użyć takich wartości jako flag, biorąc pod uwagę, że uzyskanie wartości retainCount równej większej liczbie zajęłoby prawie 3000 lat, zakładając, że wartość retainCount wzrosłaby 100 000 000 razy na sekundę.
Jakie problemy możesz napotkać stosując go? Wszystko, co robi, to zwraca liczbę zachowań obiektu. Nigdy do tego nie dzwoniłem i nie mogę wymyślić żadnego powodu, dla którego bym to zrobił. Zastąpiłem to w singletonach, aby upewnić się, że nie są one jednak cofnięte.
retainCount
do zarządzania pamięcią.
Nie powinieneś martwić się wyciekiem pamięci, dopóki aplikacja nie będzie działać i nie zrobi czegoś pożytecznego.
Gdy to nastąpi, uruchom Instruments i użyj aplikacji, aby sprawdzić, czy wycieki pamięci naprawdę się zdarzają. W większości przypadków sam stworzyłeś obiekt (a więc jesteś jego właścicielem) i zapomniałeś go zwolnić po zakończeniu.
Nie próbuj optymalizować kodu podczas jego pisania, Twoje przypuszczenia, co może spowodować wyciek pamięci lub co może zająć zbyt dużo czasu, są często błędne, gdy faktycznie używasz aplikacji normalnie.
Spróbuj napisać poprawny kod, np. Jeśli tworzysz obiekt za pomocą alokacji i tym podobnych, upewnij się, że wydałeś go poprawnie.
-retainCount
.