Nie korzystałem jeszcze z ARC, ponieważ większość kodu w projekcie, nad którym obecnie pracuję, została napisana przed iOS 5.0.
Zastanawiałem się tylko, czy wygoda braku zachowywania / publikowania ręcznie (i prawdopodobnie bardziej niezawodnego kodu, który jest wynikiem?) Przewyższa jakikolwiek „koszt” korzystania z ARC? Jakie są Twoje doświadczenia z ARC i czy możesz to polecić?
Więc:
- Jakie korzyści może przynieść ARC do projektu?
- Czy ARC ma koszt podobny do zbierania śmieci w Javie?
- Czy korzystałeś z ARC, a jeśli tak, to w jaki sposób je znalazłeś?
iphone
objective-c
ipad
ios5
automatic-ref-counting
Simon Withington
źródło
źródło
Odpowiedzi:
Nie ma wady. Użyj tego. Zrób to dzisiaj. Jest szybszy niż twój stary kod. Jest bezpieczniejszy niż twój stary kod. To jest łatwiejsze niż twój stary kod. To nie jest odśmiecanie. Nie ma narzutu czasu wykonania GC. Kompilator wstawia i zwalnia we wszystkich miejscach, które i tak powinieneś mieć. Ale jest mądrzejszy od ciebie i może zoptymalizować te, które nie są w rzeczywistości potrzebne (tak jak może rozwinąć pętle, wyeliminować zmienne tymczasowe, funkcje wbudowane itp.)
OK, teraz opowiem o małych wadach:
Jeśli jesteś wieloletnim programistą ObjC, będziesz drgać przez około tydzień, gdy zobaczysz kod ARC. Bardzo szybko przezwyciężysz to.
Istnieją pewne (bardzo) małe komplikacje w łączeniu się z kodem Core Foundation. Jest nieco więcej komplikacji w radzeniu sobie z wszystkim, co traktuje
id
jakovoid*
. Rzeczy takie jak tablice Cid
mogą wymagać trochę więcej myślenia, aby wykonać je poprawnie. Fantazyjna obsługa ObjCva_args
może również powodować problemy. Większość rzeczy związanych z matematyką na wskaźniku ObjC jest trudniejsza. W każdym razie nie powinieneś mieć tego dużo.Nie można umieścić
id
w sposóbstruct
. Jest to dość rzadkie, ale czasami służy do pakowania danych.Jeśli nie zastosowałeś prawidłowego nazewnictwa KVC i zmieszasz kod ARC i inny niż ARC, będziesz mieć problemy z pamięcią. ARC używa nazewnictwa KVC do podejmowania decyzji dotyczących zarządzania pamięcią. Jeśli to cały kod ARC, to nie ma to znaczenia, ponieważ zrobi to tak samo „źle” po obu stronach. Ale jeśli jest to mieszane ARC / inne niż ARC, oznacza to niezgodność.
ARC spowoduje wyciek pamięci podczas zgłaszania wyjątków ObjC. Wyjątek ObjC powinien być bardzo bliski zakończenia programu. Jeśli łapiesz znaczną liczbę wyjątków ObjC, używasz ich niepoprawnie. Można to naprawić za pomocą
-fobjc-arc-exceptions
, ale wiąże się to z karami omówionymi poniżej:ARC nie spowoduje wycieku pamięci podczas zgłaszania wyjątków ObjC lub C ++ w kodzie ObjC ++, ale odbywa się to kosztem wydajności czasu i przestrzeni. To kolejny z długiej listy powodów, dla których warto zminimalizować użycie ObjC ++.
ARC w ogóle nie będzie działać na iPhoneOS 3 lub Mac OS X 10.5 lub starszym. (To wyklucza mnie z używania ARC w wielu projektach).
__weak
wskaźniki nie działają poprawnie na iOS 4 lub Mac OS X 10.6, co jest wstydem, ale dość łatwe do obejścia.__weak
wskazówki są świetne, ale nie są najważniejszym punktem sprzedaży ARC.Dla ponad 95% kodu, ARC jest genialny i nie ma żadnego powodu, aby go unikać (pod warunkiem, że poradzisz sobie z ograniczeniami wersji systemu operacyjnego). W przypadku kodu innego niż ARC można przekazywać
-fno-objc-arc
plik po pliku. Niestety Xcode sprawia, że jest to znacznie trudniejsze niż powinno to być w praktyce. Prawdopodobnie powinieneś przenieść kod inny niż ARC do oddzielnego xcodeproj, aby to uprościć.Podsumowując, przełącz się na ARC tak szybko, jak to możliwe i nigdy nie oglądaj się za siebie.
EDYTOWAĆ
Widziałem kilka komentarzy w stylu „używanie ARC nie zastąpi znajomości zasad zarządzania pamięcią Cocoa”. Jest to w większości prawda, ale ważne jest, aby zrozumieć, dlaczego i dlaczego nie. Po pierwsze, jeśli cały twój kod używa ARC i naruszysz Trzy Magiczne Słowaw każdym miejscu nadal nie będziesz mieć problemów. Szokujące, ale proszę bardzo. ARC może zachować pewne rzeczy, których nie chciałeś zachować, ale uwolni je również, więc to nigdy nie będzie miało znaczenia. Gdybym dzisiaj prowadził nową klasę w kakao, prawdopodobnie spędziłbym nie więcej niż pięć minut na rzeczywistych zasadach zarządzania pamięcią i prawdopodobnie wspomniałbym tylko o regułach nazewnictwa zarządzania pamięcią, omawiając nazewnictwo KVC. Wierzę, że dzięki ARC mógłbyś zostać przyzwoitym początkującym programistą bez znajomości zasad zarządzania pamięcią.
Ale nie można było zostać przyzwoitym średniozaawansowanym programistą. Musisz znać zasady, aby poprawnie łączyć się z Core Foundation, a każdy średniozaawansowany programista musi w pewnym momencie poradzić sobie z CF. I musisz znać zasady dla mieszanego kodu ARC / MRC. I musisz znać zasady, kiedy zaczynasz bawić się
void*
wskazówkamiid
(które nadal musisz poprawnie wykonać KVO). A bloki ... cóż, zarządzanie pamięcią blokową jest po prostu dziwne.Chodzi mi więc o to, że podstawowe zarządzanie pamięcią jest nadal ważne, ale tam, gdzie spędzałem dużo czasu na określaniu i powtarzaniu reguł dla nowych programistów, dzięki ARC staje się to bardziej zaawansowanym tematem. Wolałbym, aby nowi programiści myśleli w kategoriach grafów obiektowych, zamiast wypełniać ich głowy wywołaniami do
objc_retain()
.źródło
Lepsze, bardziej techniczne odpowiedzi niż moje, ale oto idzie:
źródło
Zaletą jest znaczny stopień ochrony przed typowymi błędami w zarządzaniu pamięcią. Wycieki spowodowane niepowodzeniem zwolnienia obiektu i awarie spowodowane brakiem zachowania lub przedwczesnym zwolnieniem obiektu powinny zostać znacznie zmniejszone. Nadal musisz zrozumieć model pamięci zliczanej referencji, aby móc sklasyfikować odwołania jako silne lub słabe, uniknąć cykli zachowywania i tak dalej.
W iOS nie ma wyrzucania elementów bezużytecznych. ARC jest podobny do GC pod tym względem, że nie musisz ręcznie zachowywać ani zwalniać obiektów. W przeciwieństwie do GC, nie ma odśmiecacza. Model utrzymania / wydania nadal obowiązuje, po prostu kompilator wstawia odpowiednie wywołania zarządzania pamięcią do twojego kodu w czasie kompilacji.
To trochę niepokojące, jeśli jesteś przyzwyczajony do liczenia odniesień, ale to tylko kwestia przyzwyczajenia się do tego i nauczenia się zaufania, że kompilator naprawdę zrobi to, co trzeba. Wydaje się, że jest to kontynuacja zmiany właściwości wprowadzonej wraz z Objective-C 2.0, która była kolejnym dużym krokiem w kierunku uproszczenia zarządzania pamięcią. Bez ręcznego zarządzania pamięcią kod staje się trochę krótszy i łatwiejszy do odczytania.
Jedynym problemem z ARC jest to, że nie jest obsługiwany w starszych wersjach iOS, więc musisz wziąć to pod uwagę, zanim zdecydujesz się go zaadaptować.
źródło
Myślę, że ARC to świetny pomysł. W porównaniu do GC możesz mieć ciasto i też je zjeść. Uważam, że MRC narzuca nieocenioną „dyscyplinę” w zarządzaniu pamięcią, z której każdy skorzystałby. Ale zgadzam się również, że prawdziwym problemem, o którym należy wiedzieć, jest własność obiektu i wykresy obiektów (jak wielu wskazywało), a nie niskopoziomowe liczniki odwołań jako takie.
Podsumowując: ARC NIE jest darmową przepustką do bezmyślnego myślenia o pamięci; jest to narzędzie pomagające ludziom unikać powtarzających się zadań, które powodują stres i są podatne na błędy, dlatego lepiej delegowane na maszynę (w tym przypadku kompilator).
To powiedziawszy, osobiście jestem trochę rzemieślnikiem i jeszcze nie dokonałem przejścia. Właśnie zacząłem używać Git ...
AKTUALIZACJA: Więc zmigrowałem całą moją grę, w tym bibliotekę gl i jak dotąd żadnych problemów (z wyjątkiem asystenta migracji w Xcode 4.2). Jeśli zaczynasz nowy projekt, zrób to.
źródło
Użyłem go w kilku (co prawda małych) projektach i mam tylko dobre doświadczenia, zarówno pod względem wydajności, jak i niezawodności.
Jedną drobną uwagą jest to, że musisz nauczyć się robić: s i nie: s słabych odwołań, aby nie powodować żadnych pętli referencyjnych, jeśli sam kodujesz swój interfejs użytkownika, projektant zazwyczaj wykonuje dobrą robotę automatycznie, jeśli użyjesz go do swojego GUI.
źródło
Jedynym minusem, z jakim się spotkałem, jest to, że używasz biblioteki z wieloma funkcjami i danymi CoreFoundation. W MRC nie trzeba było martwić się o używanie
CFStringRef
zamiastNSString*
. W ARC musisz określić, w jaki sposób te dwa elementy wchodzą w interakcję (podstawowy most? Zwolnić obiekt CoreFoundation i przenieść go do ARC? Utworzyć obiekt Cocoa jako obiekt zachowany na +1 CoreFoundation?). Ponadto w systemie OS X jest dostępny tylko na 64- kod bitowy (chociaż mam nagłówek, który działa wokół tego…).źródło