Zacznijmy od retain
i release
; autorelease
to naprawdę wyjątkowy przypadek, gdy zrozumiesz podstawowe pojęcia.
W kakao każdy obiekt śledzi, ile razy jest przywoływany (w szczególności NSObject
klasa bazowa implementuje to). Wzywając retain
obiekt, mówisz mu, że chcesz zwiększyć jego liczbę odwołań o jeden. Dzwoniąc release
, mówisz obiektowi, że go puszczasz, a jego liczba referencyjna jest zmniejszana. Jeśli po wywołaniu release
liczba odwołań wynosi teraz zero, to pamięć tego obiektu jest zwalniana przez system.
Podstawowy sposób, w jaki to różni się od malloc
i free
polega na tym, że dany obiekt nie musi martwić się o awarię innych części systemu, ponieważ zwolniłeś pamięć, której używał. Zakładając, że wszyscy bawią się i zachowują / zwalniają zgodnie z regułami, gdy jeden fragment kodu zachowuje, a następnie zwalnia obiekt, żaden inny fragment kodu również odwołujący się do obiektu pozostanie niezmieniony.
Czasami mylące może być poznanie okoliczności, w których należy zadzwonić retain
i release
. Moja ogólna zasada jest taka, że jeśli chcę trzymać się obiektu przez jakiś czas (na przykład jeśli jest to zmienna składowa w klasie), muszę się upewnić, że liczba odwołań do obiektu wie o mnie. Jak opisano powyżej, liczba odwołań do obiektu jest zwiększana przez wywołanie retain
. Zgodnie z konwencją, jest on również zwiększany (naprawdę ustawiony na 1), gdy obiekt jest tworzony metodą „init”. W każdym z tych przypadków moim obowiązkiem jest wywołanie release
obiektu, kiedy z nim skończę. Jeśli tego nie zrobię, nastąpi wyciek pamięci.
Przykład tworzenia obiektu:
NSString* s = [[NSString alloc] init]; // Ref count is 1
[s retain]; // Ref count is 2 - silly
// to do this after init
[s release]; // Ref count is back to 1
[s release]; // Ref count is 0, object is freed
Teraz autorelease
. Autorelease służy jako wygodny (i czasami konieczny) sposób nakazania systemowi zwolnienia tego obiektu po chwili. Z punktu widzenia hydrauliki, gdy autorelease
jest wywoływany, bieżący wątek NSAutoreleasePool
jest powiadamiany o wywołaniu. NSAutoreleasePool
Teraz wie, że po to ma możliwość (po bieżącej iteracji pętli zdarzenia), to może zadzwonić release
na obiekcie. Z naszego punktu widzenia jako programistów dba o to, release
aby nas wzywać , więc nie musimy (a właściwie nie powinniśmy).
Ważne jest, aby pamiętać, że (ponownie zgodnie z konwencją) wszystkie metody klas tworzenia obiektów zwracają obiekt z autouzyskiwania. Na przykład w poniższym przykładzie zmienna „s” ma liczbę odwołań równą 1, ale po zakończeniu pętli zdarzenia zostanie zniszczona.
NSString* s = [NSString stringWithString:@"Hello World"];
Jeśli chcesz zawiesić się na tym łańcuchu, musisz wywołać go retain
jawnie, a następnie jawnie release
, gdy skończysz.
Rozważ następujący (bardzo wymyślny) fragment kodu, a zobaczysz sytuację, w której autorelease
jest to wymagane:
- (NSString*)createHelloWorldString
{
NSString* s = [[NSString alloc] initWithString:@"Hello World"];
// Now what? We want to return s, but we've upped its reference count.
// The caller shouldn't be responsible for releasing it, since we're the
// ones that created it. If we call release, however, the reference
// count will hit zero and bad memory will be returned to the caller.
// The answer is to call autorelease before returning the string. By
// explicitly calling autorelease, we pass the responsibility for
// releasing the string on to the thread's NSAutoreleasePool, which will
// happen at some later time. The consequence is that the returned string
// will still be valid for the caller of this function.
return [s autorelease];
}
Zdaję sobie sprawę, że to wszystko jest nieco zagmatwane - w pewnym momencie jednak kliknie. Oto kilka odniesień, które pomogą Ci zacząć:
- Wprowadzenie firmy Apple do zarządzania pamięcią.
- Cocoa Programming for Mac OS X (4th Edition) , autorstwa Aarona Hillegasa - bardzo dobrze napisana książka z wieloma świetnymi przykładami. Brzmi jak samouczek.
- Jeśli naprawdę nurkujesz, możesz udać się na Big Nerd Ranch . To ośrodek szkoleniowy prowadzony przez Aarona Hillegasa - autora wspomnianej książki. Byłem tam kilka lat temu na kursie Intro to Cocoa i był to świetny sposób na naukę.