Angenommen, ich habe eine Klasse SomeClass
mit einem string
Eigenschaftsnamen:
@interface SomeClass : NSObject
{
NSString* name;
}
@property (nonatomic, retain) NSString* name;
@end
Ich verstehe, dass dem Namen ein Name zugewiesen werden kann. NSMutableString
In diesem Fall kann dies zu fehlerhaftem Verhalten führen.
- Ist es für Zeichenfolgen im Allgemeinen immer eine gute Idee, das
copy
Attribut anstelle von zu verwendenretain
? - Ist eine "kopierte" Eigenschaft in irgendeiner Weise weniger effizient als eine solche "beibehaltene" Eigenschaft?
objective-c
cocoa
cocoa-touch
PlagueHammer
quelle
quelle
name
in veröffentlicht werdendealloc
oder nicht?Antworten:
Für Attribute, deren Typ eine unveränderliche Wertklasse ist, die dem
NSCopying
Protokoll entspricht, sollten Sie dies fast immercopy
in Ihrer@property
Deklaration angeben . Das Spezifizierenretain
ist etwas, das Sie in einer solchen Situation fast nie wollen.Hier ist, warum Sie das tun möchten:
Der aktuelle Wert der
Person.name
Eigenschaft hängt davon ab, ob die Eigenschaft deklariert istretain
odercopy
- es ist,@"Debajit"
wenn die Eigenschaft markiert istretain
, aber@"Chris"
wenn die Eigenschaft markiert istcopy
.Da Sie in fast allen Fällen verhindern möchten, dass die Attribute eines Objekts hinter seinem Rücken mutiert werden, sollten Sie die Eigenschaften markieren, die sie darstellen
copy
. (Und wenn Sie den Setter selbst schreiben, anstatt ihn zu verwenden@synthesize
, sollten Sie daran denken, ihn tatsächlich zu verwenden,copy
anstattretain
ihn zu verwenden.)quelle
NSMutableString
, außer als vorübergehender "String Builder" -Typ (von dem ich sofort eine unveränderliche Kopie nehme). Ich würde es vorziehen, wenn es sich um diskrete Typen handelt - aber ich werde zulassen, dass die Tatsache, dass die Kopie frei aufbewahrt werden kann, wenn die ursprüngliche Zeichenfolge nicht veränderbar ist, den größten Teil meiner Bedenken mindert.Für NSString sollte eine Kopie verwendet werden. Wenn es veränderlich ist, wird es kopiert. Wenn dies nicht der Fall ist, wird es einfach beibehalten. Genau die Semantik, die Sie in einer App wünschen (lassen Sie den Typ das Beste tun).
quelle
NSString
Eigenschaft, die als ohnehin deklariertcopy
wirdretain
(wenn sie unveränderlich ist, natürlich). Ein anderes Beispiel, an das ich denken kann, istNSNumber
.Ja - im Allgemeinen verwenden Sie immer das Attribut copy.
Dies liegt daran, dass Ihrer NSString-Eigenschaft eine NSString-Instanz oder eine NSMutableString-Instanz übergeben werden kann. Daher können wir nicht wirklich feststellen, ob der übergebene Wert ein unveränderliches oder veränderliches Objekt ist.
Wenn Ihrer Eigenschaft eine NSString-Instanz übergeben wird , lautet die Antwort " Nein " - das Kopieren ist nicht weniger effizient als das Beibehalten.
(Es ist nicht weniger effizient, da der NSString intelligent genug ist, um keine Kopie auszuführen.)
Wenn Ihrer Eigenschaft eine NSMutableString-Instanz übergeben wird, lautet die Antwort " Ja " - das Kopieren ist weniger effizient als das Beibehalten.
(Es ist weniger effizient, da eine tatsächliche Speicherzuweisung und -kopie erfolgen muss, dies ist jedoch wahrscheinlich wünschenswert.)
Im Allgemeinen kann eine "kopierte" Eigenschaft weniger effizient sein. Durch die Verwendung des
NSCopying
Protokolls ist es jedoch möglich, eine Klasse zu implementieren, deren Kopie "genauso effizient" ist wie deren Beibehaltung. Ein Beispiel hierfür sind NSString-Instanzen .Sie sollten immer verwenden,
copy
wenn Sie nicht möchten, dass sich der interne Status der Eigenschaft ohne Vorwarnung ändert. Selbst für unveränderliche Objekte - ordnungsgemäß geschriebene unveränderliche Objekte verarbeiten das Kopieren effizient (siehe nächster Abschnitt zu Unveränderlichkeit undNSCopying
).Es kann Leistungsgründe für
retain
Objekte geben, die jedoch mit einem Wartungsaufwand verbunden sind. Sie müssen die Möglichkeit verwalten, dass sich der interne Status außerhalb Ihres Codes ändert. Wie sie sagen - zuletzt optimieren.Nicht verwenden
copy
. Wenn Ihre Klasse wirklich unveränderlich ist, empfiehlt es sich, dasNSCopying
Protokoll so zu implementieren , dass Ihre Klasse beicopy
Verwendung selbst zurückkehrt. Wenn du das tust:copy
.copy
Annotation macht Ihren eigenen Code wartbarer - diecopy
Annotation zeigt an, dass Sie sich wirklich keine Sorgen machen müssen, dass dieses Objekt den Status an anderer Stelle ändert.quelle
Ich versuche diese einfache Regel zu befolgen:
Möchte ich den Wert des Objekts zu dem Zeitpunkt beibehalten, zu dem ich es meiner Eigenschaft zuweise? Verwendung kopieren .
Möchte ich mich an dem Objekt festhalten und es ist mir egal, welche internen Werte aktuell sind oder in Zukunft sein werden? Verwenden Sie stark (behalten).
Zur Veranschaulichung: Möchte ich an dem Namen "Lisa Miller" ( Kopie ) festhalten oder an der Person Lisa Miller ( stark ) festhalten ? Ihr Name könnte sich später in "Lisa Smith" ändern, aber sie wird immer noch dieselbe Person sein.
quelle
Anhand dieses Beispiels kann das Kopieren und Aufbewahren wie folgt erklärt werden:
Wenn die Eigenschaft vom Typ copy ist, dann
Für die
[Person name]
Zeichenfolge, die den Inhalt der Zeichenfolge enthält, wird eine neue Kopie erstelltsomeName
. Jetzt hat jede Operation an einersomeName
Zeichenfolge keine Auswirkung mehr auf[Person name]
.[Person name]
undsomeName
Zeichenfolgen haben unterschiedliche Speicheradressen.Aber im Falle der Beibehaltung,
Beide enthalten
[Person name]
dieselbe Speicheradresse wie die Somename-Zeichenfolge. Nur die Anzahl der Beibehaltungen der Somename-Zeichenfolge wird um 1 erhöht.Jede Änderung der Zeichenfolge eines Somennamens wird in der
[Person name]
Zeichenfolge wiedergegeben.quelle
Das Kopieren einer Eigenschaftsdeklaration mit "Kopieren" steht im Widerspruch zur Verwendung einer objektorientierten Umgebung, in der Objekte auf dem Heap als Referenz übergeben werden. Einer der Vorteile, die Sie hier erhalten, besteht darin, dass beim Ändern eines Objekts alle Verweise auf dieses Objekt vorhanden sind siehe die neuesten Änderungen. Viele Sprachen bieten 'ref' oder ähnliche Schlüsselwörter an, damit Werttypen (dh Strukturen auf dem Stapel) vom gleichen Verhalten profitieren können. Persönlich würde ich das Kopieren sparsam verwenden, und wenn ich der Meinung wäre, dass ein Eigenschaftswert vor Änderungen an dem Objekt geschützt werden sollte, von dem er zugewiesen wurde, könnte ich die Kopiermethode dieses Objekts während der Zuweisung aufrufen, z.
Wenn Sie das Objekt entwerfen, das diese Eigenschaft enthält, wissen natürlich nur Sie, ob das Design von einem Muster profitiert, bei dem Zuweisungen kopiert werden - Cocoawithlove.com hat Folgendes zu sagen:
"Sie sollten einen Kopier-Accessor verwenden, wenn der Setter-Parameter möglicherweise veränderbar ist, der interne Status einer Eigenschaft jedoch nicht ohne Vorwarnung geändert werden kann." Die Entscheidung, ob Sie den Wert für eine unerwartete Änderung aushalten können, liegt also ganz bei Ihnen. Stellen Sie sich dieses Szenario vor:
In diesem Fall nimmt unser Kontaktobjekt ohne Verwendung der Kopie automatisch den neuen Wert an. Wenn wir es jedoch verwenden würden, müssten wir manuell sicherstellen, dass Änderungen erkannt und synchronisiert werden. In diesem Fall kann es wünschenswert sein, die Semantik beizubehalten. In einem anderen Fall ist eine Kopie möglicherweise besser geeignet.
quelle
quelle
Sie sollten Gebrauch kopieren die ganze Zeit NSString Eigenschaft zu erklären
Sie sollten diese lesen, um weitere Informationen darüber zu erhalten, ob eine unveränderliche Zeichenfolge zurückgegeben wird (falls eine veränderbare Zeichenfolge übergeben wurde) oder eine beibehaltene Zeichenfolge zurückgegeben wird (falls eine unveränderliche Zeichenfolge übergeben wurde).
NSCopying-Protokollreferenz
Wertobjekte
quelle
Da der Name ein (unveränderlicher) Name ist
NSString
, macht das Kopieren oder Behalten keinen Unterschied, wenn Sie einen anderenNSString
Namen festlegen . Mit anderen Worten, das Kopieren verhält sich wie das Beibehalten und erhöht die Referenzanzahl um eins. Ich denke, das ist eine automatische Optimierung für unveränderliche Klassen, da sie unveränderlich sind und nicht geklont werden müssen. Wenn jedoch aNSMutalbeString
mstr
auf name gesetzt ist, wird der Inhalt vonmstr
aus Gründen der Richtigkeit kopiert.quelle
Wenn die Zeichenfolge sehr groß ist, wirkt sich das Kopieren auf die Leistung aus, und zwei Kopien der großen Zeichenfolge benötigen mehr Speicher.
quelle