ETA: @DougW richtig weist darauf hin, dass eine Eigentumsform Eigentum (assign
/retain
/copy
) wirkt sich nicht auf den Getter. Es wirkt sich immer noch auf den Setter aus. Für readonly
Typen ist dies wichtig, wenn Sie den readonly
-Teil der Deklaration in einer Klassenerweiterung überschreiben, sodass Sie den Setter innerhalb Ihrer Implementierung verwenden können. Eine Überschreibungseigenschaft der Klassenerweiterung darf nur den readonly
-Status der Eigenschaft ändern, daher muss der Rest der Klasse - also die Atomizitäts- und Besitzertypen - in der Kopfzeile entsprechend deklariert werden. Selbst wenn Sie die Property jetzt nicht überschreiben, könnten Sie dies in Zukunft tun, also können Sie genauso gut dokumentieren, wie der Speicher für Sie verwaltet werden soll, indem Sie zunächst die richtige Option verwenden.
Automatische Referenzzählung (ARC) ändert die Laufzeitimplementierungsdetails, indem die eigenen Speicherverwaltungsregeln über die klassischen Refcount-Regeln gelegt werden. Die Regeln und Hinweise für die Konfiguration Ihrer Eigenschaften bleiben jedoch gleich.
Warum retain
mit readonly
verwenden? Wenn Sie eine Immobilie als retain
, die synthetisierte Accessor markieren tut etwas wie folgt aus:
/* getter for retain property */
- (NSString *)name {
return [[name retain] autorelease];
}
Nun, wenn das Objekt, das Sie -name
gesendet den Namen ändert, während Sie immer noch in Gebrauch ist, wird der anrufende Code noch haben ein gültiger Verweis auf eine Zeichenfolge.Wenn Sie es als assign
erklärt, obwohl, würde es so sein:
/* getter for assign property */
- (NSString *)name {
return name;
}
Nun, sobald Name durch das Objekt geändert wird, wird es freigegeben werden muß, um ein Leck zu vermeiden, die die Berufung ungültig werden Code-Referenz. Die retain
/copy
/assign
ist wirklich eine Speicher-Management-Richtlinie: retain
/copy
sagt: "Ich verspreche, dass ich einen Verweis auf das Original/eine Kopie des Wertes, den ich hier zur Verfügung stellen", während assign
sagt, "Ich habe nur der Wert und behaupten, keinen Bezug darauf zu haben. "
Wenn der Wert keine Speicherverwaltung benötigt, z. B. eine einfache int
, dann ist assign
sinnvoll. Wenn Sie absichtlich ein Objekt wie einen Delegaten nicht beibehalten, ist assign
sinnvoll. In den meisten anderen Fällen benötigen Sie jedoch retain
oder copy
.
Weiter kann die Implementierungsdatei nur den Teil readwrite
/readonly
einer Eigenschaftsdeklaration überschreiben, nicht den Speicherverwaltungsteil. Wie erklärt, kann die .m
Datei:
@interface Holiday (/*class extension*/)
@property(nonatomic, retain, readwrite) NSDate *date;
/* override other properties to make them readwrite... */
@end
Nicht-öffentliche Setter für die überschriebene Eigenschaft Erklärungen werden dann zusammen mit den öffentlichen Accessoren synthetisiert werden.
Warum nicht Setter/Accessoren während -init
verwenden? Da Setter/Accessoren häufig KVO-Benachrichtigungen ausführen, die Sie vermeiden möchten, während Ihr Objekt nicht vollständig initialisiert wird, z. B. -init
(wenn es auf dem Weg zur vollständigen Initialisierung zur Hälfte initialisiert wird) und -dealloc
(wenn es halb initialisiert ist) Möglichkeit, vollständig uninitialisiert zu werden).
Warum copy
mit readonly
verwenden? Als Antwort auf Ihre erste Frage: weil, wenn copy
gegenüber retain
gegenüber assign
betrifft sowohl die Setter und die Getters. Eine Kopie Getter würde wie folgt aussehen:
/* getter for copy property */
- (NSString *)name {
return [[name copy] autorelease];
}
Warum manchmal copy
und manchmal retain
?copy
wird normalerweise mit Wertobjekten verwendet (passive Objekte, die einen Wert darstellen); retain
wird normalerweise mit anderen Objekten verwendet. Manchmal kommen Effizienzprobleme ins Spiel (höchstwahrscheinlich zu früh ...), und Sie könnten sich dafür entscheiden, retain
zu verwenden, wo Sie normalerweise copy
verwenden würden.
Wie würden Sie copy
/retain
zusammen mit readonly
hier verwenden? So ziemlich wie sie es taten. Ich würde die Deklarationen in einer Klassenerweiterung überschreiben, so dass ich Setter verwenden kann, um die Werte der Eigenschaften außerhalb von -init
und -dealloc
zu ändern, wo ich nur den Variablenzugriff der direkten Instanz verwenden würde. Ich würde auch nil
aus dem ivars nach ihnen in -dealloc
Freigabe, zum Beispiel
[name release], name = nil;
Dies hilft, das Senden von Nachrichten zu vermeiden oder auf andere Weise Referenzierung ein bereits freigegeben Objekts.
** nichtatomare ** beibehalten Eigenschaften geben Sie einfach den Zeiger zurück. Sie tun ** nicht das behalten, Autorelease-Ding. Siehe den Abschnitt ** Atomizität ** der Dokumentation http://developer.apple.com/library/ios/# Dokumentation/Kakao/Konzeptionelle/ObjectiveC/Artikel/ocProperties.html – JeremyP
@ JeremyP: Guter Ruf. Die Entscheidung, bei nicht-atomaren Zugriffsmethoden die "[[foo retain] Autorelease"] nicht beizubehalten, macht Sinn: Wenn Sie den Wert länger als den aktuellen Runloop-Zyklus festhalten, sollten Sie ihn selbst behalten. Wenn Sie 'nichtatomisch' verwenden, heißt das grundsätzlich, dass die Thread-Sicherheit keine Rolle spielt. Wenn Sie sich nicht um die Threadsicherheit kümmern müssen, wird kein Code neben Ihrem ausgeführt, während Sie den Rückgabewert vom Accessor verwenden. Daher ist es für den Accessor nicht notwendig, '[[foo retain] autorelease]' 'auszuführen . –
@ Jeremy: Ich würde so weit gehen, zu sagen, dass Sie mit nichtatomaren Mitteln sagen, dass Robustheit kein Problem ist - oder weniger als Leistung betrifft. Das Festlegen von Eigenschaften auf nichtatomisch, ohne zuerst den Code zu profilieren, zählt als vorzeitige Optimierung in meinem Buch. – JeremyP