2 Stimmen

Was sind die Vor- und Nachteile dieser verschiedenen Freigabestrategien?

Ich habe verschiedene Ansätze für die Speicherverwaltung in iOS gesehen, was die Freigabe von Eigenschaften betrifft. Nach einigen Diskussionen mit Kollegen sind die Vor- und Nachteile in meinem Kopf durcheinandergeraten.

Ich hoffe, eine Zusammenfassung der Vor- und Nachteile zu erhalten, die es mir und anderen ermöglicht, einen Standardansatz zu wählen und gleichzeitig zu verstehen, wann man Ausnahmen machen sollte. Hier sind die 3 Varianten, die ich gesehen habe:

Angenommen, @property (nonatomic, retain) MyObject *foo;

// Release-only. Seems to be the favored approach in Apple's sample code.
- (void)dealloc {
    [foo release];
    [super dealloc];
}

// Property accessor set to nil.
- (void)dealloc {
    self.foo = nil;
    [super dealloc];
}

// Release, then nil.
- (void)dealloc {
    [foo release];
    foo = nil;
    [super dealloc];
}

Wenn Sie eine andere Variante hinzufügen möchten, kommentieren Sie hier und ich werde den Beitrag bearbeiten.

2voto

idz Punkte 12413

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.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X