Versionen (1): ist die beste. Jede der anderen hat Eigenschaften, die schädlich sein können.
Version (2): Es wird allgemein empfohlen, keine Accessoren in dealloc (oder init) zu verwenden. Der Grund dafür ist, dass das Objekt gerade abgerissen (oder erstellt) wird und sich in einem inkonsistenten Zustand befindet. Dies gilt insbesondere, wenn Sie eine Bibliothek schreiben, in der jemand anderes später einen Accessor überschreiben kann, ohne zu wissen, dass er aufgerufen werden kann, wenn sich das Objekt in einem inkonsistenten Zustand befindet. (Natürlich bricht sogar Apple manchmal diese Regel -[UIView initWithFrame:]
ruft auf. -[UIView setFrame:]
wenn das Argument nicht CGRectZero
was die Fehlersuche unterhaltsam machen kann.
Version (3); Einstellung des ivar auf nil
dient keinem nützlichen Zweck, sondern kann sogar einen Fehler maskieren und die Fehlersuche mehr schwierig. Um zu sehen, warum dies der Fall ist, betrachten Sie das folgende Stück Code, angenommen myObject hat eine Version (3) dealloc
.
FastMovingTrain* train = [[FastMoving alloc] init];
MyObject* myObject = [[MyObject alloc] init];
myObject.foo = train;
[train release];
// my myObject.foo is the only thing retaining train
...
....
[myObject release];
// Because of version (3) dealloc if myObject
// points to the dealloced memory this line
// will silently fail...
[myObject.foo applyBrakes];
Interessanterweise bietet dieser Code die Möglichkeit zu demonstrieren, dass das Setzen einer Variablen auf nil
nach einer release
macht durchaus Sinn. Der Code kann wie folgt geändert werden, um ihn widerstandsfähiger zu machen.
FastMovingTrain* train = [[FastMoving alloc] init];
MyObject* myObject = [[MyObject alloc] init];
myObject.foo = train;
[train release];
// my myObject.foo is the only thing retaining train
...
....
[myObject release];
myObject = nil;
// This assertion will fail.
NSAssert(myObject, @"myObject must not be nil");
[myObject.foo applyBrakes];
Nur meine $0,02.