Prawidłowe użycie accesorów w metodach INIT i dealloc?

Słyszałem teraz z kilku źródeł (stackoverflow.com, cocoa-dev, dokumentacja, blogi itp.), że "źle" jest używać accesorów i ustawień (foo, setFoo:) w metodach init i dealloc. Rozumiem, że istnieje odległa możliwość mylenia innych obiektów, które obserwują właściwość, jeśli to zrobisz. (prosty przykład podano TUTAJ )

Muszę jednak powiedzieć, że nie zgadzam się z tą praktyką z następującego powodu:

Nowy Objective - C runtime (ten na iPhonie i 64-bitowy runtime w wersji 10.5) pozwala na deklarowanie właściwości Bez deklarowania odpowiedniego ivar. Na przykład, następująca Klasa skompiluje się dobrze na 10.5 lub dla iPhone ' a (urządzenie, nie symulator):

@interface Foo : NSObject { }

  @property (retain) id someObject;

@end

@implementation Foo

  @synthesize someObject;

@end

Rozumiejąc, że powyższe jest doskonale poprawną klasą Objective-C, powiedzmy, że zdecyduję się napisać inicjalizator, a dla celów zarządzania pamięcią, metodę dealloc (ponieważ GC nie jest dostępna na iPhone ' ie). Wszystko, co kiedykolwiek czytałem o inicjalizatorach i dealokacji, doprowadziłoby mnie do napisania następujących dwóch metod:

- (id) init {
  if (self = [super init]) {
    //initialize the value of someObject to nil
    [self setSomeObject:nil];
  }
  return self;
}

- (void) dealloc {
  //setting someObject to nil will release the previous value
  [self setSomeObject:nil];
  [super dealloc];
}

Jednak, zgodnie z dokumentacją i popularną opinią, jest to "złe". Więc moje pytania są takie:

  1. Jak mam zainicjować someObject bez użycia accessora? Można powiedzieć, że kompilator (lub runtime lub cokolwiek innego) zapewni, że someObject jest już ustawiony na nil, ale uważam, że niewłaściwe zachowanie byłoby polegać na tym. Mając przyzwoite tło w C, widziałem sporo błędów z powodu nieprawidłowej inicjalizacji zmiennych, a to wydaje się trochę inne.
  2. Jak mogę zwolnić someObject, jeśli nie powinienem używać accessora w metodzie dealloc?

Jeśli odpowiedź na którąkolwiek z nich brzmi "nie możesz", to jak może być źle używać accesorów w metodach init i dealloc?

Author: Community, 2009-08-16

2 answers

Rozumiem, że obecne zachowanie 10.5, w którym zsyntetyzowane Ivary nie są bezpośrednio dostępne, jest uważane przez Apple za błąd; powinieneś mieć bezpośredni dostęp do niego, ale nie możesz.

Dlatego powinieneś umieć:

someObject = nil;

Zamiast

self.someObject = nil;

W międzyczasie, korzystanie bezpośrednio z accessora jest jedynym sposobem, aby to zrobić bez podania jawnego ivar.

Update: ten błąd został naprawiony; możesz teraz zrobić someObject = nil po prostu dobrze.

 8
Author: BJ Homer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-09 23:56:58

EDIT (Luty 13, 2013): Jak wspomniano w moim komentarzu poniżej, a zwłaszcza od dodania ARC, zmieniłem zdanie na ten temat. Przed Arc widziałem wiele błędów powodujących awarie z powodu błędnych zadań ivar w init. IMO, szczególnie pracując z juniorskimi drużynami, rzadkie problemy z używaniem accesorów w init były przeważane przez typowe błędy ivar access. Ponieważ ARC wyeliminował tego rodzaju błędy, rzadkie, ale możliwe błędy, które może spowodować użycie accessora w init są bardziej ważne, więc przerzuciłem się na wspieranie bezpośredniego korzystania z ivars w init i dealloc, i tylko w tych miejscach; Accesory wszędzie tam, gdzie jest to możliwe (oczywiście nie można używać accesorów wewnątrz samego accesora....)


odpowiedź przed ARC

Zdecydowanie nie zgadzam się z tymi, którzy sprzeciwiają się accessorom w -init. W prawie wszystkich przypadkach jest to bardzo dobre miejsce do korzystania z accesorów i oszczędza wiele błędów, które widziałem w nowych koderach Cocoa, którzy niezmiennie nie potrafią zachowaj przy przypisywaniu w -init.

-dealloc to trudniejsza decyzja. Mam naturalną skłonność do używania tam accesorów( tak, aby były używane wszędzie), ale może to powodować bóle głowy z powodu KVO (lub nawet NSNotifications, jeśli opublikujesz powiadomienie o zmianie w setterze). To powiedziawszy, chociaż nie używam accesorów w -dealloc, uważam to za bardzo dyskusyjne, a Apple jest bardzo niespójne co do tego (wiemy, że wywołują setView: w UIViewController ' s -dealloc na przykład).

W każdym razie, chciałbym powiedzmy, że niedostateczne użycie accesorów spowodowało 100x błędy nadmiernego użycia. Zawsze błądziłbym w kierunku korzystania z nich, chyba że istnieje silny powód, aby tego nie robić.

 9
Author: Rob Napier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-13 08:05:35