2009-08-16 10 views
9

Istnieje wiele przypadków, w których można przydzielić instancję i zwolnić ją zaraz po przypisaniu jej do czegoś innego, co zachowuje ją wewnętrznie.Czy lepiej jest autorelease lub zwolnić zaraz po?

Na przykład

 
UIView *view = [[UIView alloc] initWithFrame...]; 
[self addSubView:view]; 
[view release]; 

Słyszałem ludzi sugerując, że idziemy z autorelease niż zaraz po wydaniu.

Więc powyższe staje:

 
UIView *view = [[[UIView alloc] initWithFrame...] autorelease]; 
[self addSubView:view]; 

Jaka jest najlepsza praktyka tutaj? Plusy i minusy?

Odpowiedz

14

W większości przypadków tak naprawdę nie ma to znaczenia. Ponieważ -autorelease oznacza po prostu, że obiekt zostanie zwolniony na końcu bieżącej iteracji pętli, obiekt zostanie zwolniony w dowolny sposób.

Największą korzyścią z używania -autorelease jest to, że nie musisz martwić się o czas życia obiektu w kontekście twojej metody. Tak więc, jeśli później zdecydujesz, że chcesz zrobić coś z obiektem kilka linii po ostatnim użyciu, nie musisz się martwić o przeniesienie połączenia do -release.

Głównym przykład podczas korzystania -release uczyni zauważalnej różnicy vs. użyciu -autorelease jest jeśli tworzysz dużo tymczasowych obiektów w swojej metodzie. Na przykład, rozważmy następujący sposób:

- (void)someMethod { 
    NSUInteger i = 0; 
    while (i < 100000) { 
     id tempObject = [[[SomeClass alloc] init] autorelease]; 

     // Do something with tempObject 

     i++; 
    } 
} 

Do czasu metoda ta kończy, masz 100.000 obiektów siedzi w puli autorelease czeka być zwolniony. W zależności od klasy tempObject może to być problemem, ale na pewno dotyczy to tylko iPhone'a z ograniczoną pamięcią. Tak więc powinieneś naprawdę używać -release przez -autorelease, jeśli alokujesz wiele tymczasowych obiektów. Ale dla wielu/większości zastosowań nie zauważysz żadnych poważnych różnic między tymi dwoma.

+3

+1. autorelease powoduje dużo problemów z wydajnością (flak rzadko widziałem kopie zapasowe z liczbami w normalnym, niezbyt dużym kodzie), ale autoreasowanie również oszczędza wiele nieszczelności, gdy kod zostanie refaktoryzowany. Używam wydania częściej w procedurach niskiego poziomu, ponieważ nie wiem, czy można je nazwać dużą pętlą na wyższym poziomie. Jeśli jednak zamierzasz używać wydania, musisz natychmiast ustawić zmienną na zero, jeśli zmienna nadal będzie znajdować się w zasięgu. Nigdy nie zwalniaj obiektu, ale nadal masz na nim wskaźnik. –

5

Zgadzam się z Matt Ball. Niech mi tylko dodać, że jeśli okaże się stosując ten wzór często, może to być przydatne, aby napisać krótki kategorię:

@interface UIView (MyCategories) 
- (UIView *)addNewSubviewOfType:(Class)viewType inFrame:(NSRect)frame; 
@end 

@implementation UIView (MyCategories) 
- (UIView *)addNewSubviewOfType:(Class)viewType inFrame:(NSRect)frame 
{ 
    UIView * newView = [[viewType alloc] initWithFrame:frame]; 
    [self addSubView:newView]; 
    return [newView autorelease]; 
} 
@end 

które mogą być używane w następujący sposób:

UIView * view = [someView addNewSubviewOfType:[UIView class] 
             inFrame:someFrame]; 

a nawet prace z innych typów, tak długo jak są one pochodzących z UIView:

UIButton * button = [mainView addNewSubviewOfType:[UIButton class] 
              inFrame:buttonFrame]; 
4

zazwyczaj na -release zamiast -autorelease miarę możliwości. Wynika to z wieloletniego doświadczenia w debugowaniu i ulepszaniu kodu Celive-C dla innych ludzi. Kod używający autoreleaseu wszędzie sprawia, że ​​trudniej jest debugować, gdy obiekt zostanie nadmiernie zwolniony, ponieważ dodatkowe wydanie odbywa się z dala od nieprawidłowego kodu.

Jest także tak, że wielu ludzi używa autorelease, gdy nie rozumieją, jak działa zarządzanie pamięcią kakao. Poznaj zasady, poznaj API, a prawie nigdy nie będziesz musiał autorelease obiektu.

Ostatnim drobnym punktem jest to, że jeśli nie potrzebujesz zachowania autorelease, to używanie autorelease po prostu niepotrzebnie dodaje dodatkową pracę do twojego programu.

Powiązane problemy