Frage

Was ist der Unterschied zwischen den folgenden zwei Möglichkeiten zuweisen und init ein Objekt?

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

und

self.aController= [[AController alloc] init];

Die meisten des Apfels Beispiel die erste Methode verwenden. Warum würden Sie vergeben, init und Objekt und dann sofort wieder loslassen?

War es hilfreich?

Lösung

Jedes Objekt hat einen Referenzzähler. Wenn es auf 0 geht, wird das Objekt freigegeben.

die Eigenschaft Angenommen wurde als @property (retain) erklärt:

Ihr erstes Beispiel, Zeile für Zeile:

  1. Die Aufgabe wird durch alloc erstellt wird, eine Referenzzählung von 1 hat.
  2. Das Objekt wird in self der setAController: Methode übergeben, die eine retain Nachricht sendet (da das Verfahren nicht weiß, wo das Objekt herkommt), den Referenzzähler auf 2 erhöht wird.
  3. Die Telefonvorwahl muss nicht mehr das Objekt selbst, so ruft es release, den Referenzzähler auf 1 dekrementiert.

Ihr zweites Beispiel hat im Grunde die Schritte 1 und 2, aber nicht mehr als 3, am Ende so die Referenzzählung des Objekts beträgt 2.

Die Regel ist, dass, wenn Sie ein Objekt erstellen, können Sie für die Freigabe verantwortlich sind, wenn Sie mit ihm fertig sind. In Ihrem Beispiel wird der Code mit tempAController getan, nachdem er die Eigenschaft legt. Es ist die Verantwortung der Setter-Methode retain zu nennen, wenn es um das Objekt braucht um zu bleiben.

Es ist wichtig, dass self.property = foo; in Objective-C erinnern wirklich eine Abkürzung ist nur für [self setProperty:foo]; und dass die setProperty: Verfahren beibehalten oder Kopieren von Objekten werden werden je nach Bedarf.

Wenn die Eigenschaft @property (copy) erklärt wurde, dann würde das Objekt wurde statt beibehalten hat kopiert. Im ersten Beispiel würde das ursprüngliche Objekt freigegeben sofort werden; in dem zweiten Beispiel der Referenzzähler ursprüngliche Objekt würde 1 auch sein, obwohl es 0. Also sollten Sie dennoch wollen Ihren Code auf die gleiche Weise schreiben.

Wenn die Eigenschaft @property (assign) erklärt wurde, dann self behauptet, nicht das Eigentum an dem Objekt, und jemand anderes muss es behalten. In diesem Fall wäre das erste Beispiel falsch sein. Diese Art von Eigenschaften sind selten, in der Regel nur für die Objekt Delegierten verwendet.

Andere Tipps

Wie andere bereits erwähnt haben, sind die beiden Code-Snippets Sie zeigen nicht gleichwertig sind (für die Speicherverwaltung Gründen). Wie, warum die ehemaligen über letzteren gewählt wird:

Die richtige Formulierung des letzteren wäre

self.aController= [[[AController alloc] init] autorelease];

mit dem früheren Vergleich, fügt dieser zusätzlichen Aufwand durch die Verwendung des Autofreigabepools, und in einigen Fällen werden die Lebensdauer des Objekts führt unnötig verlängert wird (bis der Autofreigabepool freigegeben wird), die Ihre Anwendung Speicherbedarf zu erhöhen.

Die andere „möglich“ Implementierung (je nachdem, wo das Beispiel aus) ist einfach:

aController = [[AController alloc] init];

Allerdings Einstellung direkt eine Instanzvariable ist stark irgendwo anders als in einer init oder dealloc Methode abgeraten. An anderer Stelle sollten Sie immer Accessormethoden verwenden.

Das bringt uns dann auf die Umsetzung in Beispielcode dargestellt:

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

Dies ergibt sich am besten Praxis seit:

  • Sie vermeidet Autofreigabe;
  • Es macht die Speicherverwaltung Semantik sofort klar;
  • Es verwendet eine Accessor-Methode die Instanz-Variable zu setzen.

Beachten Sie auch, dass Ihr Wunsch, den Code bis auf eine Linie zu schneiden ist, warum viele Menschen Autorelease verwenden:

self.aController = [[[AController alloc] init] autorelease];

Obwohl in der Theorie auf dem iPhone Autorelease irgendwie teurer ist (nie eine klare Erklärung gehört, warum) und damit können Sie explizit rechts freigeben mögen, nachdem Sie das an anderer Stelle Objekt zuweisen.

Wenn Sie Xcode verwenden, kann es Ihnen helfen einen solchen Code mit dem statischen Analysator zu erfassen. Einfach auf >> Bauen Bauen und Analysieren

alt text

Dies zeigt Ihnen eine sehr hilfreiche Nachricht an solchen Code-Teilen.

alt text

Eine andere Sache zu beachten ist, dass Ihr Beispiel auf der @property Definition von AController abhängt.

Wenn es als @property (readwrite, retain) id aController; definiert wurde dann Ihr Beispiel funktioniert, während, wenn sie als @property (readwrite, assign) id aController; definiert wird dann der zusätzliche Anruf würde dazu führen, lassen Sie Ihr Objekt freigegeben werden.

Sie können auch tun

@property (nonatomic, retain)AController *aController;
...
self.aController= [[AController alloc] init];
[aController release];

mit einer Rückhalteeigenschaft, und es würde die gleiche Art und Weise funktionieren, aber es ist besser, die andere Art und Weise zu verwenden (für Eigenschaften beibehalten werden), weil es weniger verwirrend ist, dass Code macht es so aussehen wie Sie AController zuweisen und dann wird es aus dem Speicher gelöscht wenn tatsächlich ist es nicht, weil setAController behält es.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top