Soweit ich weiß, werden seit XCode 4.4 @synthesize
die Eigenschafts-Accessoren automatisch generiert. Aber gerade jetzt habe ich ein Codebeispiel darüber gelesen NSUndoManager
und im Code festgestellt, dass das @synthesize
explizit hinzugefügt wird. Mögen:
@interface RootViewController ()
@property (nonatomic, strong) NSDateFormatter *dateFormatter;
@property (nonatomic, strong) NSUndoManager *undoManager;
@end
@implementation RootViewController
//Must explicitly synthesize this
@synthesize undoManager;
Ich bin jetzt verwirrt ... Wann sollte ich @synthesize
meinen Code explizit ergänzen ?
@sythesize
. Wenn der Code immer noch funktioniert, ist er nicht erforderlich.Antworten:
Es gibt viele Antworten, aber auch große Verwirrung. Ich werde versuchen, etwas Ordnung zu schaffen (oder das Chaos zu erhöhen, wir werden sehen ...)
Hören wir auf, über Xcode zu reden. Xcode ist eine IDE . clang ist ein Compiler . Diese Funktion, die wir diskutieren, wird als Autosynthese von Eigenschaften bezeichnet und ist eine Objective-C-Spracherweiterung, die von clang unterstützt wird , dem von Xcode verwendeten Standard-Compiler.
Nur um es klar zu machen: Wenn Sie in Xcode zu gcc wechseln, profitieren Sie nicht von dieser Funktion (unabhängig von der Xcode-Version). Ebenso wie Sie, wenn Sie einen Texteditor verwenden und mit clang über die Befehlszeile kompilieren werden.
Dank der Autosynthese müssen Sie die Eigenschaft nicht explizit synthetisieren, da sie vom Compiler automatisch als synthetisiert wird
@synthesize propertyName = _propertyName
Es gibt jedoch einige Ausnahmen:
readwrite-Eigenschaft mit benutzerdefiniertem Getter und Setter
bei der Bereitstellung von sowohl eine Getter und Setter benutzerdefinierte Implementierung wird die Eigenschaft nicht automatisch synthetisiert werden
schreibgeschützte Eigenschaft mit benutzerdefiniertem Getter
Wenn Sie eine benutzerdefinierte Getter-Implementierung für eine schreibgeschützte Eigenschaft bereitstellen, wird diese nicht automatisch synthetisiert
@dynamic
Bei Verwendung
@dynamic propertyName
wird die Eigenschaft nicht automatisch synthetisiert werden (ziemlich offensichtlich, da@dynamic
und@synthesize
sich gegenseitig aus)Eigenschaften, die in einem @protocol deklariert sind
Bei Übereinstimmung mit einem Protokoll wird eine vom Protokoll definierte Eigenschaft nicht automatisch synthetisiert
Eigenschaften, die in einer Kategorie deklariert sind
Dies ist ein Fall, in dem die
@synthesize
Direktive vom Compiler nicht automatisch eingefügt wird, diese Eigenschaften jedoch auch nicht manuell synthetisiert werden können. Während Kategorien Eigenschaften deklarieren können, können sie überhaupt nicht synthetisiert werden, da Kategorien keine Ivars erstellen können. Der Vollständigkeit halber möchte ich hinzufügen, dass es immer noch möglich ist , die Eigenschaftssynthese mithilfe der Objective-C-Laufzeit zu fälschen .überschriebene Eigenschaften (neu seit clang-600.0.51, Versand mit Xcode 6, danke Marc Schlüpmann)
Wenn Sie eine Eigenschaft einer Oberklasse überschreiben, müssen Sie sie explizit synthetisieren
Es ist erwähnenswert, dass beim Synthetisieren einer Eigenschaft das Backing-Ivar automatisch synthetisiert wird. Wenn also die Eigenschaftssynthese fehlt, fehlt auch das Ivar, sofern nicht ausdrücklich deklariert.
Mit Ausnahme der letzten drei Fälle besteht die allgemeine Philosophie darin, dass
@dynamic
der Compiler bei jeder manuellen Angabe aller Informationen zu einer Eigenschaft (durch Implementierung aller Zugriffsmethoden oder Verwendung ) davon ausgeht, dass Sie die vollständige Kontrolle über die Eigenschaft wünschen, und die Autosynthese deaktiviert es.Abgesehen von den oben aufgeführten Fällen besteht die einzige andere Verwendung eines Expliziten
@synthesize
darin, einen anderen Ivar-Namen anzugeben. Da Konventionen jedoch wichtig sind, empfehle ich, immer die Standardbenennung zu verwenden.quelle
@synthesize
eine Kategorie verboten ist (kein Ivar in Kategorien, wie Sie bereits bemerkt haben). Ich werde eine Notiz hinzufügen.Wenn Sie
@synthesize
den Compiler nicht explizit verwenden, wird Ihre Eigenschaft genauso verstanden, wenn Sie geschrieben haben@synthesize undoManager=_undoManager;
dann können Sie in Ihren Code Dinge schreiben wie:
[_undoManager doSomething]; // iVar [self.undoManager doSomethingElse]; // Use generated getter
Dies ist die übliche Konvention.
wenn du schreibst
@synthesize undoManager;
du wirst haben :
[undoManager doSomething]; // iVar [self.undoManager doSomethingElse]; // Use generated getter
Persönlich höre ich auf zu benutzen
@synthesize
, da es nicht mehr obligatorisch ist. Für mich ist der einzige Grund zu verwenden@synthesize
, einiVar
mit einem zu verknüpfen@property
. Wenn Sie einen bestimmten Getter und Setter dafür generieren möchten. Aber in dem gegebenen Code gibt es keineiVar
, ich denke, dass dies@synthesize
nutzlos ist. Aber jetzt denke ich, die neue Frage ist "Wann verwendeniVar
?", Und ich habe keine andere Antwort als "nie" für diese!quelle
@synthesize
da es keinen Grund mehr gibt, es zu tun. Der führende Unterstrich dient auch als schönes visuelles Flag, um Sie darüber zu informieren, dass Sie sich mit dem Speicherverwaltungs- und Threading-Sicherheitsnetz befassen, das die Eigenschaften bieten (die Sie überspringen sollten,init
unddealloc
Methoden).Wann sollte ich
@synthesize
meinen Code explizit ergänzen ?Im Allgemeinen, wenn es erforderlich ist: Sie werden wahrscheinlich nie einen Fall treffen, in dem es erforderlich ist.
Es gibt jedoch einen Fall, den Sie vielleicht nützlich finden.
Angenommen, Sie schreiben sowohl einen benutzerdefinierten Getter als auch einen Setter, möchten jedoch, dass eine Instanzvariable diesen unterstützt. (Für eine atomare Eigenschaft ist dies so einfach wie der Wunsch nach einem benutzerdefinierten Setter: Der Compiler schreibt einen Getter, wenn Sie einen Setter für eine einatomige Eigenschaft angeben, jedoch keine atomare Eigenschaft.)
Bedenken Sie:
@interface MyObject:NSObject @property (copy) NSString *title; @end @implementation MyObject - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end
Dies wird nicht funktionieren, da
_title
es nicht existiert. Sie haben sowohl einen Getter als auch einen Setter angegeben, sodass Xcode (korrekt) keine Hintergrundinstanzvariable dafür erstellt.Sie haben zwei Möglichkeiten, um es zu schaffen. Sie können entweder Folgendes ändern
@implementation
:@implementation MyObject { NSString *_title; } - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end
Oder ändern Sie es in Folgendes:
@implementation MyObject @synthesize title = _title; - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end
Mit anderen Worten, obwohl Synthetisieren für praktische Zwecke niemals erforderlich ist *, kann es verwendet werden, um Instanzvariablen zur Sicherung von Eigenschaften zu definieren , wenn Sie einen Getter / Setter bereitstellen. Hier können Sie entscheiden, welches Formular Sie verwenden möchten.
In der Vergangenheit habe ich es vorgezogen, die Instanzvariable in der anzugeben
@implementation {}
, aber jetzt denke ich, dass die@synthesize
Route eine bessere Wahl ist, da sie den redundanten Typ entfernt und die Hintergrundvariable explizit an die Eigenschaft bindet:@synthesize
wird ein Compilerfehler generiert. Sie werden nicht mit streunenden Instanzvariablen enden.* -Ich kenne einen Fall, in dem es notwendig war, die Funktionalität auf Kategorien in mehrere Dateien aufzuteilen. Und ich wäre nicht überrascht, wenn Apple dies behebt oder sogar schon behebt.
quelle
atomic
erst später als Eigenschaftsspezifizierer hinzugefügt wurde. Jetzt, wo es da ist, könnte die WarnflaggeCLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES
interessant sein.OK, wenn Sie eine Eigenschaft erstellen ...
@property NSString *name;
Xcode synthetisiert automatisch einen iVar, als hätten Sie geschrieben ...
@synthesize name = _name;
Dies bedeutet, dass Sie mit ...
self.name; // or _name;
Beides funktioniert, verwendet jedoch nur
self.name
die Accessor-Methoden.Es gibt nur ein Mal, dass die automatische Synthese nicht funktioniert: Wenn Sie nur den Setter UND die Getter-Methode überschreiben, müssen Sie den iVar synthetisieren.
Sie sind in Ordnung, wenn Sie nur den Setter überschreiben oder wenn Sie nur den Getter überschreiben. Wenn Sie jedoch beides tun, wird der Compiler es nicht verstehen und Sie müssen es manuell synthetisieren.
Als Faustregel gilt jedoch.
Mach keine iVars. Nutzen Sie einfach die Eigenschaft. Synthetisiere es nicht.
quelle
Die Eigenschaftssynthese ist erforderlich, wenn eine Eigenschaft in einem Protokoll deklariert ist. Es wird nicht automatisch in einer Implementierungsschnittstelle synthetisiert.
quelle
Vielen Dank für die Klarstellung. Ich hatte ein ähnliches Problem.
@synthesize firstAsset, secondAsset, audioAsset; @synthesize activityView;
Nachdem ich sie auskommentiert hatte, ging ich durch und ersetzte zum Beispiel jedes Vorkommen durch
self.firstAsset Es scheint, dass ich auch firstAsset verwenden könnte, aber ich vermisse es, das " " zu oft zu sehen.
quelle
Xcode erfordert keine explizite
@synthesize
Deklaration.Wenn Sie nicht schreiben, ist es
@synthesize
dasselbe wie:@synthesize manager = _manager;
Der Beispielcode war möglicherweise alt. Sie werden es bald aktualisieren.
Sie können auf Ihre Eigenschaften zugreifen wie:
[self.manager function];
Dies ist die von Apple empfohlene Konvention. Ich folge ihm und empfehle Ihnen, dies auch zu tun!
quelle
[_manager function]
greift NICHT auf die Eigenschaft zu, sondern direkt auf das zugrunde liegende ivar .[_manager function]
keine Accessoren der Eigenschaft verwendet werden.