2009-09-07 18 views
8

Coś, co przez jakiś czas zastanawiałem się nad właściwościami. Czy przy korzystaniu z właściwości należy przesłonić komunikat o zwolnieniu, aby upewnić się, że właściwości są zwalnianymi właściwościami?Czy jest wymagane zwolnienie pamięci Objective-c 2.0?

tj. jest wystarczającym przykładem (fikcyjnym)?

@interface MyList : NSObject { 
NSString* operation; 
NSString* link; 
} 
@property (retain) NSString* operation; 
@property (retain) NSString* link; 
@end 

@implementation MyList 
@synthesize operation,link; 
@end 
+1

Ponieważ NSString potwierdza protokół NSCopying, lepiej jest użyć @property (kopiowanie, ReadWrite) NSString * operacja Ponadto, jeśli stosujemy nowoczesne czasy pracy, nie trzeba określić zmienne instancji: będą zsyntetyzowane również. Aby dowiedzieć się więcej, wyszukaj "Podręcznik programowania Objective-C 2.0" firmy Apple i poszukaj sekcji zatytułowanych "Atrybuty deklaracji właściwości" i "Dyrektywy implementacji właściwości". –

+0

+1 świetne pytanie, zastanawiałem się dokładnie to samo dokładnie – andy

Odpowiedz

13

Zawsze należy zwolnić zmienne poparcie w dealloc:

- (void) dealloc { 
    [operation release]; 
    [link release]; 

    [super dealloc]; 
} 

inny sposób:

- (void) dealloc { 
    self.operation = nil; 
    self.link = nil; 

    [super dealloc]; 
} 

to nie jest preferowanym sposobem zwolnienia obiektów, ale w przypadku, gdy używasz zsyntetyzowanych zmiennych pomocniczych, jest to jedyny sposób, aby to zrobić.

UWAGA: aby było jasne, dlaczego to działa, spójrzmy na syntetyzowanych realizacji seter dla Link nieruchomości, a co się dzieje, gdy jest on ustawiony na nil:

- (void) setLink:(MyClass *) value { 
    [value retain]; // calls [nil retain], which does nothing 
    [link release]; // releases the backing variable (ivar) 
    link = value; // sets the backing variable (ivar) to nil 
} 

WIĘC efekt netto jest taki, że uwolni to ivar.

+1

Właściwie, jeśli używasz syntetyzowanych ivars (tzn. Deklarujesz właściwość, ale nie odpowiadającą jej ivar), to zostanie wygenerowany dla ciebie ivar. Zobacz moje pytanie tutaj: http://stackoverflow.com/questions/1283419 –

+3

Niektóre kompilatory nie zsyntetyzowały ivar. Naprawiono to po wydaniu pierwszego kompilatora obsługującego syntezowane ivars. Stąd zamieszanie. – bbum

+0

@bbum dobrze wiedzieć! Dziękuję za wyjaśnienie. –

1

Nie, zastępujesz metodę -dealloc. I owszem, jeśli nie zwolnisz swoich właściwości (lub raczej podkładów ivars), wyciekniesz. Więc w @implementation tutaj trzeba mieć coś podobnego

- (void)dealloc { 
    [operation release]; 
    [link release]; 
    [super dealloc]; 
} 
3

W aplikacjach non-GC, tak. Zwykle przypisuje się zero zamiast zwalniać ivars. Moim najlepszym doświadczeniem jest zwolnienie sekwencji ivar zainicjalizowanych przez init i przypisanie wartości zerowej właściwościom z trybem zatrzymania i kopiowania.

W twoim przypadku byłoby przypisać zerowe

- (void) dealloc { 
    self.operation = nil; 
    self.link = nil; 
    [super dealloc]; 
} 
+1

To jest jedyny poprawny sposób na zrobienie tego. –

+1

@gs nie jest poprawny. Możesz zwolnić ivar i ustawić je na zero bezpośrednio. Korzystanie z akcesorów może powodować dziwne efekty uboczne w rzadkich przypadkach. Jeśli obserwujesz właściwość obiektu, a obiekt jest ustawiony na zero, twój obserwator może próbować uzyskać inne informacje z obiektu, ale jeśli set-to-nil wydarzyłby się w -dealloc, mogły się zdarzyć dziwne rzeczy. –

+0

To jest dziwactwo składni. Ktoś życzy sobie zsyntetyzowanego lub niejawnego "@properties_release();" może zostać dodana do metody dealloc, w niektórych przyszłych specyfikacjach językowych. Jeśli celem C 2.0 będą wszystkie rzeczy dla wszystkich ludzi, wydaje się dziwne, aby polecić coś takiego, jak ta składnia accessor, a następnie umieścić na nim zastrzeżenie dotyczące obserwatorów i obiektów dostępowych w destruktorach. –

1

syntetyzowania właściwość tylko tworzy metody getter i setter, a do nich nie wyda ivar gdy obiekt jest zwalniane. Musisz uwolnić ivar samodzielnie.

+1

Dotyczy to tylko deklarowanych właściwości, które * nie * używają atrybutu default (assign). Wyszukaj "Podręcznik programowania Objective-c 2.0" firmy Apple i przeczytaj sekcję "Deklarowane właściwości", w szczególności część dotyczącą dealloc. I quot wycinek: "Zadeklarowane właściwości dają jednak użyteczny sposób na sprawdzenie implementacji twojej metody dealloc: możesz wyszukać wszystkie deklaracje właściwości w pliku nagłówkowym i upewnić się, że właściwości obiektu nie oznaczone są przypisane, a te oznaczone jako przypisek nie są zwalniane. " –

2

Najlepszym sposobem, aby to zrobić:

- (void)dealloc { 
    [operation release], operation = nil; 
    [link release], link = nil; 

    [super dealloc]; 
} 

To rzeczywiście może być bardziej wygodny w użyciu wygenerowanych metod ustawiających

self.operation = nil; 

ale że jest mile widziana. Nie zawsze wiesz, do którego wątku jest przydzielany obiekt. Tak więc używanie akcesora może powodować problemy poprzez wyzwalanie powiadomień KVO.

Połów tutaj polega na tym, że musisz dostosować swój dealloc, aby pasował do polityki zarządzania obiektami zdefiniowanej w twojej @ dziedziczności. Na przykład. nie wypuszczaj nośnika iVar wspierającego właściwość (assign).

0

W przypadku wstępnego ARC za każdym razem, gdy widzisz nowe, przydzielane, zachowywane i kopiowane, niezależnie od tego, czy jest to instancja var, czy właściwość, którą musisz zwolnić. W ARC, gdy masz silną zmienną, musisz ustawić ją na zero. W obu przypadkach musisz zastąpić dealloc().

Powiązane problemy