@property behalten, zuweisen, kopieren, nichtatomar in Objective-C

214

Kann mir jemand, der neu in Objective-C ist, einen Überblick über das Aufbewahren, Zuweisen, Kopieren und andere fehlende Elemente geben, die der @ property-Direktive folgen? Was machen sie und warum sollte ich sie übereinander verwenden wollen?

Mark Reid
quelle
1
Apples Name für diese ist "Attribute" oder "Eigenschaftsattribute"
Nevan King

Antworten:

273

Der von MrMage verlinkte Artikel funktioniert nicht mehr. Folgendes habe ich in meiner (sehr) kurzen Zeitcodierung in Objective-C gelernt:

nichtatomar vs. atomar - "atomar" ist die Standardeinstellung. Verwenden Sie immer "nichtatomar". Ich weiß nicht warum, aber das Buch, das ich gelesen habe, sagte, dass es "selten einen Grund" gibt, "atomar" zu verwenden. (Übrigens: Das Buch, das ich gelesen habe, ist das BNR-Buch "iOS Programming".)

readwrite vs. readonly - "readwrite" ist die Standardeinstellung. Wenn Sie @synthesize verwenden, werden sowohl ein Getter als auch ein Setter für Sie erstellt. Wenn Sie "schreibgeschützt" verwenden, wird kein Setter erstellt. Verwenden Sie es für einen Wert, den Sie nach der Instanziierung des Objekts nicht mehr ändern möchten.

behalten vs. kopieren vs. zuweisen

  • "zuweisen" ist die Standardeinstellung. In dem von @synthesize erstellten Setter wird der Wert einfach dem Attribut zugewiesen. Mein Verständnis ist, dass "zuweisen" für Nicht-Zeiger-Attribute verwendet werden sollte.
  • "behalten" wird benötigt, wenn das Attribut ein Zeiger auf ein Objekt ist. Der von @synthesize generierte Setter behält das Objekt bei (auch bekannt als Hinzufügen einer Aufbewahrungsanzahl). Sie müssen das Objekt freigeben, wenn Sie damit fertig sind.
  • "copy" wird benötigt, wenn das Objekt veränderbar ist. Verwenden Sie diese Option, wenn Sie den aktuellen Wert des Objekts benötigen und nicht möchten, dass dieser Wert Änderungen widerspiegelt, die von anderen Eigentümern des Objekts vorgenommen wurden. Sie müssen das Objekt freigeben, wenn Sie damit fertig sind, da Sie die Kopie behalten.
Blamdarot
quelle
@Blamdarot - muss ich es auch mit ARC veröffentlichen
Dejell
10
@Odelya - Nein. Wenn Sie während der Verwendung von ARC freigeben, wird meiner Meinung nach ein Compilerfehler angezeigt.
Blamdarot
52
"Immer nichtatomar verwenden" ist ein schlechter Rat. Sie sollten wissen, was Sie aufgeben, wenn Sie nichtatomar verwenden.
Jesse Rusak
7
Einverstanden. Insbesondere scheinen viele Leute nicht zu wissen, dass nichtatomare Werte vom Getter nicht automatisch freigegeben werden. Nichtatomar ist oft angemessen, aber Frachtkultprogrammierung selten.
Catfish_Man
9
Die Empfehlung, die Standardeinstellung beizubehalten, atomicist genauso schlecht wie die Empfehlung nonatomic. Keine der beiden Optionen ist die "richtige", daher entschieden sich die Sprachdesigner für die sicherere der beiden Lösungen. In der Tat nonatomicist im Allgemeinen die bessere Wahl, da extrem teure Gewindesperren weggelassen werden. Der einzige Grund für die Verwendung atomicbesteht darin, dass Ihre Eigenschaft möglicherweise aus mehreren Threads besteht (in diesem Fall kann das Auslassen zu einer Überfreigabe oder einem Leck führen).
Adam Kaplan
295

Bevor Sie die Attribute von @property kennen, sollten Sie wissen, wie @property verwendet wird.

  • @property bietet eine Möglichkeit, die Informationen zu definieren, die eine Klasse kapseln soll. Wenn Sie ein Objekt / eine Variable mit @property deklarieren , können andere Klassen, die ihre Klasse importieren, auf dieses Objekt / diese Variable zugreifen .

  • Wenn Sie ein Objekt mit @property in der Header-Datei deklarieren , müssen Sie es mit @synthesize in der Implementierungsdatei synthetisieren . Dies macht das Objekt KVC-konform . Standardmäßig synthetisiert der Compiler Zugriffsmethoden für dieses Objekt.

  • Accessor-Methoden sind: Setter und Getter.

Beispiel: .h

@interface XYZClass : NSObject
@property (nonatomic, retain) NSString *name;
@end

.m

@implementation XYZClass
@synthesize name;
@end

Jetzt synthetisiert der Compiler Accessor-Methoden für den Namen .

XYZClass *obj=[[XYZClass alloc]init];
NSString *name1=[obj name]; // get 'name'
[obj setName:@"liza"]; // first letter of 'name' becomes capital in setter method
  • Liste der Attribute von @property

    atomar, nichtatomar, beibehalten, kopieren, schreibgeschützt, schreibgeschützt, zuweisen, stark, getter = Methode, setter = Methode, unsafe_unretained

  • Atomic ist das Standardverhalten. Wenn ein Objekt als atomar deklariert ist, wird es threadsicher. Thread-sicher bedeutet, dass jeweils nur ein Thread einer bestimmten Instanz dieser Klasse die Kontrolle über dieses Objekt haben kann.

Wenn der Thread eine Getter-Methode ausführt, kann ein anderer Thread keine Setter-Methode für dieses Objekt ausführen. Es ist langsam.

@property NSString *name; //by default atomic`
@property (atomic)NSString *name; // explicitly declared atomic`
  • Nichtatomar ist nicht threadsicher. Sie können das nichtatomare Eigenschaftsattribut verwenden, um anzugeben, dass synthetisierte Accessoren einfach einen Wert direkt festlegen oder zurückgeben, ohne Garantie dafür, was passiert, wenn auf denselben Wert gleichzeitig von verschiedenen Threads aus zugegriffen wird.

Aus diesem Grund ist der Zugriff auf eine nichtatomare Eigenschaft schneller als auf eine atomare.

@property (nonatomic)NSString *name;   
  • Beibehalten ist erforderlich, wenn das Attribut ein Zeiger auf ein Objekt ist.

Die Setter-Methode erhöht die Aufbewahrungsanzahl des Objekts, sodass es den Speicher im Autorelease-Pool belegt.

@property (retain)NSString *name;
  • copy Wenn Sie copy verwenden, können Sie keep nicht verwenden. Die Verwendung der Kopierinstanz der Klasse enthält eine eigene Kopie.

Selbst wenn eine veränderbare Zeichenfolge festgelegt und anschließend geändert wird, erfasst die Instanz den Wert, den sie zum Zeitpunkt der Festlegung hat. Es werden keine Setter- und Getter-Methoden synthetisiert.

@property (copy) NSString *name;

jetzt,

NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"];    
xyzObj.name = nameString;    
[nameString appendString:@"Pizza"]; 

Name bleibt unberührt.

  • schreibgeschützt Wenn Sie nicht möchten, dass die Eigenschaft über die Setter-Methode geändert wird, können Sie die Eigenschaft schreibgeschützt deklarieren.

Der Compiler generiert einen Getter, aber keinen Setter.

@property (readonly) NSString *name;
  • readwrite ist das Standardverhalten. Sie müssen das readwrite-Attribut nicht explizit angeben.

Es ist das Gegenteil von readonly.

@property (readwrite) NSString *name;
  • Zuweisen generiert einen Setter, der den Wert direkt der Instanzvariablen zuweist, anstatt ihn zu kopieren oder beizubehalten. Dies ist am besten für primitive Typen wie NSInteger und CGFloat oder für Objekte geeignet, die Sie nicht direkt besitzen, z. B. Delegaten.

Beachten Sie, dass Beibehalten und Zuweisen grundsätzlich austauschbar sind, wenn die Speicherbereinigung aktiviert ist.

@property (assign) NSInteger year;
  • stark ist ein Ersatz für behalten.

Es kommt mit ARC.

@property (nonatomic, strong) AVPlayer *player; 
  • getter = method Wenn Sie einen anderen Namen für eine getter-Methode verwenden möchten, können Sie einen benutzerdefinierten Namen angeben, indem Sie der Eigenschaft Attribute hinzufügen.

Bei booleschen Eigenschaften (Eigenschaften mit einem JA- oder NEIN-Wert) beginnt die Getter-Methode üblicherweise mit dem Wort "is".

@property (getter=isFinished) BOOL finished;
  • setter = method Wenn Sie einen anderen Namen für eine Setter-Methode verwenden möchten, können Sie einen benutzerdefinierten Namen angeben, indem Sie der Eigenschaft Attribute hinzufügen.

Die Methode sollte mit einem Doppelpunkt enden.

@property(setter = boolBool:) BOOL finished;
  • unsafe_unretained Es gibt einige Klassen in Cocoa und Cocoa Touch, die noch keine schwachen Referenzen unterstützen. Dies bedeutet, dass Sie keine schwache Eigenschaft oder schwache lokale Variable deklarieren können, um diese zu verfolgen. Diese Klassen umfassen NSTextView, NSFont und NSColorSpace usw. Wenn Sie eine schwache Referenz auf eine dieser Klassen verwenden müssen, müssen Sie eine unsichere Referenz verwenden.

Eine unsichere Referenz ähnelt einer schwachen Referenz dahingehend, dass das zugehörige Objekt nicht am Leben bleibt, jedoch nicht auf Null gesetzt wird, wenn die Zuordnung des Zielobjekts aufgehoben wird.

@property (unsafe_unretained) NSObject *unsafeProperty;

Wenn Sie mehrere Attribute angeben müssen, fügen Sie diese einfach als durch Kommas getrennte Liste hinzu:

@property (readonly, getter=isFinished) BOOL finished;
Liza
quelle
Schwach bedeutet außerdem, dass es keinen Referenzzähler für das Objekt gibt, auf das verwiesen wird, sondern dass es überhaupt oder überhaupt nicht referenziert wird. Ein bisschen wie "yep, etwas hat mich referenziert" vs. "9 Referenzen auf mich existieren" (wie stark ist).
Alex Zavatone
6
Ignorieren Sie die Zeile in der Antwort zur Speicherbereinigung, da die Speicherbereinigung in Mac OS X veraltet und in iOS gemäß Apple-Dokumentation nicht vorhanden ist .
Basil Bourque
4
"Hinweis: Die Atomizität von Eigenschaften ist nicht gleichbedeutend mit der Thread-Sicherheit eines Objekts." - von developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
jk7
1
„Wenn Sie ein Objekt mit deklarieren @propertyin der Header - Datei, dann Sie müssen es synthetisieren unter Verwendung @synthesizein der Implementierungsdatei.“ Nicht immer. Beispiel: "Standardmäßig wird eine readwriteEigenschaft durch eine Instanzvariable gesichert, die vom Compiler automatisch wieder synthetisiert wird." Aus doc .
Franklin Yu
4
@ Liza Dies ist eine ausgezeichnete Antwort. Warum ist dies nicht die akzeptierte Antwort. Es vermittelt eine weitaus sachkundigere Erklärung als die derzeit akzeptierte Antwort. Ich verstehe StackOverflow manchmal nicht?
Charles Robertson
149

Nachdem ich viele Artikel gelesen hatte, beschloss ich, alle Attributinformationen zusammenzustellen:

  1. atomar // Standard
  2. nichtatomar
  3. strong = beibehalten // Standard
  4. schwach = unsicher_unretained
  5. behalten
  6. // Standard zuweisen
  7. unsafe_unretained
  8. Kopieren
  9. schreibgeschützt
  10. readwrite // default

Unten finden Sie einen Link zu dem ausführlichen Artikel, in dem Sie diese Attribute finden.

Vielen Dank an alle, die hier die besten Antworten geben !!

Variable Eigenschaftsattribute oder Modifikatoren in iOS

Hier ist die Beispielbeschreibung aus dem Artikel

  1. atomar -Atomic bedeutet, dass nur ein Thread auf die Variable zugreift (statischer Typ). -Atomic ist threadsicher. - Aber die Leistung ist langsam. - Atomic ist das Standardverhalten. - Atomic Accessors in einer Umgebung, in der kein Müll gesammelt wurde (dh bei Verwendung von Retain / Release / Autorelease), verwenden eine Sperre, um sicherzustellen, dass ein anderer Thread die korrekte Einstellung / das richtige Abrufen nicht beeinträchtigt des Wertes. -es ist eigentlich kein Schlüsselwort.

Beispiel:

@property (retain) NSString *name;

@synthesize name;
  1. nonatomic -Nonatomic bedeutet, dass mehrere Threads auf die Variable zugreifen (dynamischer Typ). -Nonatomic ist Thread unsicher. -aber es ist schnell in der Leistung -Nonatomic ist NICHT Standardverhalten, wir müssen nichtatomares Schlüsselwort im Eigenschaftsattribut hinzufügen. -es kann zu unerwartetem Verhalten führen, wenn zwei verschiedene Prozesse (Threads) gleichzeitig auf dieselbe Variable zugreifen.

Beispiel:

@property (nonatomic, retain) NSString *name;

@synthesize name;

Erklären:

Angenommen, es gibt eine atomare Zeichenfolgeeigenschaft mit dem Namen "name". Wenn Sie [self setName: @ "A"] von Thread A aus aufrufen, rufen Sie [self setName: @ "B"] von Thread B aus auf und rufen Sie [self name] von auf Thread C, dann werden alle Operationen an verschiedenen Threads seriell ausgeführt. Wenn also ein Thread Setter oder Getter ausführt, warten andere Threads. Dies macht das Lesen / Schreiben der Eigenschaft "Name" sicher, aber wenn ein anderer Thread D gleichzeitig [Namensfreigabe] aufruft, kann dieser Vorgang einen Absturz verursachen, da hier kein Setter / Getter-Aufruf beteiligt ist. Dies bedeutet, dass ein Objekt schreib- / schreibsicher (ATOMIC), aber nicht threadsicher ist, da andere Threads gleichzeitig jede Art von Nachrichten an das Objekt senden können. Entwickler sollten die Thread-Sicherheit für solche Objekte gewährleisten.

Wenn die Eigenschaft "Name" nichtatomar war, werden alle Threads im obigen Beispiel - A, B, C und D gleichzeitig ausgeführt und erzeugen ein unvorhersehbares Ergebnis. Im Fall von Atomic wird entweder A, B oder C zuerst ausgeführt, D kann jedoch weiterhin parallel ausgeführt werden.

  1. strong (iOS4 = behalten) - es heißt "behalte dies auf dem Haufen, bis ich nicht mehr darauf zeige" - mit anderen Worten "ich bin der Besitzer, du kannst dies nicht freigeben, bevor du gut mit dem gleichen Ziel wie" behalten "zielst - - Sie verwenden strong nur, wenn Sie das Objekt beibehalten müssen. Standardmäßig sind alle Instanzvariablen und lokalen Variablen starke Zeiger. - Wir verwenden im Allgemeinen stark für UIViewController (die Eltern des UI-Elements). - Stark wird mit ARC verwendet und hilft Ihnen im Grunde, indem Sie sich nicht um die Anzahl der Objekte kümmern müssen. ARC gibt es automatisch für Sie frei, wenn Sie damit fertig sind. Wenn Sie das Schlüsselwort strong verwenden, bedeutet dies, dass Sie das Objekt besitzen.

Beispiel:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;
  1. schwach (iOS4 = unsafe_unretained) - es heißt "Behalte dies, solange jemand anderes stark darauf hinweist" - dasselbe wie Zuweisen, kein Zurückhalten oder Freigeben - Eine "schwache" Referenz ist eine Referenz, die Sie nicht behalten. - Wir verwenden im Allgemeinen schwach für IBOutlets (UIViewController's Childs). Dies funktioniert, weil das untergeordnete Objekt nur so lange existieren muss, wie das übergeordnete Objekt. -eine schwache Referenz ist eine Referenz, die das referenzierte Objekt nicht vor der Sammlung durch einen Garbage Collector schützt. -Schwach ist im Wesentlichen zuweisen, eine nicht beibehaltene Eigenschaft. Außer wenn das Objekt freigegeben wird, wird der schwache Zeiger automatisch auf Null gesetzt

Beispiel:

@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

Starke und schwache Erklärung, danke an BJ Homer :

Stellen Sie sich vor, unser Objekt ist ein Hund und der Hund möchte weglaufen (freigegeben werden). Starke Zeiger sind wie eine Leine am Hund. Solange Sie die Leine am Hund befestigt haben, rennt der Hund nicht weg. Wenn fünf Personen ihre Leine an einem Hund befestigen (fünf starke Zeiger auf ein Objekt), rennt der Hund nicht weg, bis alle fünf Leinen gelöst sind. Schwache Zeiger hingegen sind wie kleine Kinder, die auf den Hund zeigen und sagen: "Schau! Ein Hund!" Solange der Hund noch an der Leine ist, können die kleinen Kinder den Hund noch sehen und sie werden immer noch darauf zeigen. Sobald jedoch alle Leinen gelöst sind, rennt der Hund weg, egal wie viele kleine Kinder darauf zeigen. Sobald der letzte starke Zeiger (Leine) nicht mehr auf ein Objekt zeigt, wird die Zuordnung des Objekts aufgehoben und alle schwachen Zeiger werden auf Null gesetzt. Wann verwenden wir schwach? Das einzige Mal, wenn Sie schwach verwenden möchten, ist, wenn Sie Aufbewahrungszyklen vermeiden möchten (z. B. behält der Elternteil das Kind und das Kind behält den Elternteil, sodass keiner jemals freigegeben wird).

  1. behalten = stark -es wird beibehalten, alter Wert wird freigegeben und zugewiesen -retain gibt an, dass der neue Wert gesendet werden soll -retain bei Zuweisung und der alte gesendete Wert -release -retain ist der gleiche wie strong. -apple sagt, wenn Sie behalten, wird es automatisch konvertiert / funktioniert nur wie stark. -Methoden wie "Zuweisen" beinhalten ein implizites "Beibehalten"

Beispiel:

@property (nonatomic, retain) NSString *name;

@synthesize name;
  1. assign -assign ist die Standardeinstellung und führt einfach eine variable Zuordnung -assign eine Eigenschaft Attribut ist , das den Compiler , wie sagt die Unterkunft Setter Implementierung zu synthetisieren -I für C primitive Eigenschaften und schwach für schwache Verweise auf Objective-C - Objekte verwendet assign würde.

Beispiel:

@property (nonatomic, assign) NSString *address;

@synthesize address;
  1. unsafe_unretained

    -unsafe_unretained ist ein Besitzqualifikationsmerkmal, das ARC mitteilt, wie Aufbewahrungs- / Freigabeaufrufe eingefügt werden sollen. -unsafe_unretained ist die ARC-Version von assign.

Beispiel:

@property (nonatomic, unsafe_unretained) NSString *nickName;

@synthesize nickName;
  1. copy -copy ist erforderlich, wenn das Objekt veränderbar ist. -copy gibt an, dass der neue Wert gesendet werden soll -copy bei Zuweisung und der alte Wert gesendet werden -release. -copy ist so, als würde keep ein Objekt zurückgeben, das Sie explizit freigeben müssen (z. B. in Dealloc), in Umgebungen, in denen kein Müll gesammelt wurde. -Wenn Sie eine Kopie verwenden, müssen Sie diese weiterhin im Dealloc freigeben. - Verwenden Sie diese Option, wenn Sie den Wert des Objekts in diesem Moment benötigen und nicht möchten, dass dieser Wert Änderungen widerspiegelt, die von anderen Eigentümern des Objekts vorgenommen wurden. Sie müssen das Objekt freigeben, wenn Sie damit fertig sind, da Sie die Kopie behalten.

Beispiel:

@property (nonatomic, copy) NSArray *myArray;

@synthesize myArray;
swiftBoy
quelle
2
Ich denke, nach dem Lichtbogen wird Retain nicht mehr verwendet.
Mert
1
In der vollständigen Liste fehlen zwei Optionselemente: Setter und Getter, die ebenfalls die einzigen Optionen sind, für die ein Argument erforderlich ist.
Scott Chu
stark oder beibehalten ist standardmäßig nur für den Objekttyp. Es kann nicht für primitive Typen verwendet werden.
Saleh Enam Shohag
9

Auf die atomare Eigenschaft kann jeweils nur ein Thread zugreifen. Es ist threadsicher . Die Standardeinstellung ist atomar. Bitte beachten Sie, dass kein Schlüsselwort atomar vorhanden ist

Nichtatomar bedeutet, dass mehrere Threads auf das Element zugreifen können. Der Thread ist unsicher

Daher sollte man bei der Verwendung von Atomic sehr vorsichtig sein, da dies die Leistung Ihres Codes beeinträchtigt

Kannan Prasad
quelle
3
"Hinweis: Die Atomizität von Eigenschaften ist nicht gleichbedeutend mit der Thread-Sicherheit eines Objekts." von developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
jk7