Was genau macht @synthesize?

148

Ich habe den folgenden Code gesehen:

//example.h
MKMapView * mapView1;
@property (nonatomic, retain) MKMapView * mapView;

//example.m
@synthesize mapView = mapView1

Wie ist die Beziehung zwischen mapViewund mapView1? Erstellt es eine setund getMethode für mapView1?

Hoang Duy Nam
quelle
1
Update: aber mit dem neuesten Tool-Set wird @synthesize jetzt (fast) nie mehr benötigt. Siehe Antwort auf die Frage "Anderer Stapelüberlauf" .
Ali Beadle

Antworten:

228

In Ihrem Beispiel mapView1handelt es sich um eine Instanzvariable (ivar), einen Speicher, der zu einer Instanz der in example.hund definierten Klasse gehört example.m. mapViewist der Name einer Eigenschaft . Eigenschaften sind Attribute eines Objekts, die mit der Punktnotation gelesen oder festgelegt werden können : myObject.mapView. Eine Eigenschaft nicht haben , um auf einem Ivar basieren, aber die meisten Eigenschaften sind. Die @propertyErklärung sagt der Welt einfach, dass es eine Eigenschaft namens gibt mapView.

@synthesize mapView = mapView1;

Diese Zeile weist den Compiler an, einen Setter und einen Getter für zu erstellen und mapViewden aufgerufenen ivar zu verwenden mapView1. Ohne das = mapView1Teil würde der Compiler annehmen, dass die Eigenschaft und ivar denselben Namen haben. (In diesem Fall würde dies einen Compilerfehler erzeugen, da kein ivar aufgerufen wird mapView.)

Das Ergebnis dieser @synthesizeAnweisung ähnelt dem, wenn Sie diesen Code selbst hinzugefügt haben:

-(MKMapView *)mapView
{
   return mapView1;
}

-(void)setMapView:(MKMapView *)newMapView
{
  if (newMapView != mapView1)
  {
    [mapView1 release];
    mapView1 = [newMapView retain];
  }
}

Wenn Sie diesen Code selbst zur Klasse hinzufügen, können Sie die @synthesizeAnweisung durch ersetzen

@dynamic mapView;

Die Hauptsache ist eine sehr klare konzeptionelle Unterscheidung zwischen Ivaren und Eigenschaften. Sie sind wirklich zwei sehr unterschiedliche Konzepte.

Felixyz
quelle
31

@synthesize Erstellt einen Getter und einen Setter für die Variable.

Auf diese Weise können Sie einige Attribute für Ihre Variablen angeben. Wenn Sie @synthesizediese Eigenschaft für die Variable verwenden, generieren Sie den Getter und Setter für die Variable.

Der Eigenschaftsname kann mit dem Variablennamen identisch sein. Manchmal möchten die Benutzer, dass es anders ist, um es in initoder deallocoder wenn der Parameter mit demselben Variablennamen übergeben wird, zu verwenden.

Wodkhang
quelle
16

Aus der Dokumentation :

Sie verwenden das Schlüsselwort @synthesize, um dem Compiler mitzuteilen, dass er die Setter- und / oder Getter-Methoden für die Eigenschaft synthetisieren soll, wenn Sie sie nicht im @ Implementierungsblock angeben.

Dave DeLong
quelle
8

Da ich beim Bearbeiten von Legacy-Code gerade auf dieses Problem stoße, möchte ich zusätzliche Notizen zu den vorhandenen Antworten machen, die man beachten muss.

Selbst mit einer neueren Compilerversion macht es manchmal einen Unterschied, ob Sie weglassen @synthesize propertyNameoder nicht .

In dem Fall, dass Sie eine Instanzvariable ohne Unterstrich deklarieren, während Sie sie noch synthetisieren, wie z.

Header:

@interface SomeClass : NSObject {
   int someInt;
}
@property int someInt;
@end

Implementierung:

@implementation SomeClass
@synthesize someInt;
@end

self.someIntgreift auf dieselbe Variable zu wie someInt. Die Verwendung eines führenden Unterstrichs für Ivars folgt nicht den Namenskonventionen, aber ich bin gerade in eine Situation geraten, in der ich solchen Code lesen und ändern musste.

Aber wenn Sie jetzt denken "Hey, @synthesize ist nicht mehr wichtig, da wir einen neueren Compiler verwenden" , liegen Sie falsch! Ihre Klasse führt dann zu zwei Ivaren , nämlich someInteiner automatisch generierten_someInt Variablen. So self.someIntund someIntdie gleichen Variablen nicht mehr ansprechen. Wenn Sie ein solches Verhalten wie ich nicht erwarten, kann dies zu Kopfschmerzen führen.

Lars Blumberg
quelle
"synchronisieren"! = "synthetisieren"?
Jameshfisher
Ja, das sind 2 verschiedene Konzepte. @synchronizeist eine Anweisung zum Synchronisieren von Threads beim Zugriff auf die Eigenschaft und @synthesizezum Binden der Eigenschaft an eine Instanzvariable über Getter und Setter.
Lars Blumberg
1
Der Kommentar von jameshfisher sollte Sie darauf aufmerksam machen, dass Sie die Synchronisierung und Synthese in Ihrer Antwort verwirrt haben. Sie verwenden die beiden austauschbar.
Maple
1
Danke, dass du mich darauf aufmerksam gemacht hast! Ich habe das völlig überwacht und die Antwort aktualisiert, um das nicht vorhandene Schlüsselwort @synchronize nicht zu verwenden.
Lars Blumberg
In diesem Fall warnt xcode 10 vor dem Problem : Autosynthesized property 'someInt' will use synthesized instance variable '_someInt', not existing instance variable 'someInt'. (Ich weiß nicht, in welcher Version von xcode diese Warnung hinzugefügt wurde.)
zwcloud
7

Gemäß der Apple-Dokumentation wird @Synthesize nur zum Umbenennen von Instanzvariablen verwendet. Beispielsweise

@property NSString *str;

@synthesize str = str2; 

Jetzt in der Klasse können Sie nicht verwenden, _strda die obige Zeile die Instanzvariable in umbenannt hatstr2

@property Ermöglicht die Verwendung von Objekten durch Objekte in anderen Klassen oder macht das Objekt mit anderen Worten öffentlich.

PT Vyas
quelle
3
Anscheinend unterstützt Clang ab Xcode 4.4 die Autosynthese deklarierter Eigenschaften. Daher ist @synthesize in den meisten Fällen nicht mehr erforderlich. Siehe useyourloaf.com/blog/2012/08/01/…
huyz
5

Wenn Sie eine Eigenschaft in @interface erstellen, wird diese Eigenschaft automatisch von einer Instanzvariablen mit dem Namen _propertyName zurückgegeben. Wenn Sie also eine Eigenschaft mit dem Namen firstName erstellen, erstellt der Compiler hinter den Kulissen standardmäßig eine Instanzvariable mit dem Namen _firstName. Der Compiler erstellt auch die Getter- und Setter-Methode für Sie (dh firstName, setFirstName).

Wenn Sie nun die Eigenschaft mit @synthesize firstName synthetisieren, teilen Sie dem Compiler einfach mit, dass meine Instanzvariable (_firstName) durch firstName umbenannt wird. Wenn Sie Ihre gesicherte Instanzvariable mit einem anderen Namen umbenennen möchten, können Sie einfach einen anderen Namen zuweisen, während Sie den Eigenschaftsnamen synthetisieren (dh @synthesize firstName = myFirstName). Auf diese Weise wird Ihre Eigenschaft durch eine Instanzvariable mit dem Namen myFirstname gesichert.

Kurz gesagt, @synthesize wurde die meiste Zeit verwendet, um Ihre von Ihrer Eigenschaft gesicherte Instanzvariable umzubenennen.

Mahadev Mandale
quelle
2

Siehe die Apple-Dokumente

Grundsätzlich erstellt die Synthese eine setMapView- und eine mapView-Methode, die mapView1 setzt und abruft

mmmmmm
quelle
2

Es erstellt Getter und Setter für Ihr Objekt. Sie können mit so etwas zugreifen:

MKMapView* m = object.mapView;

oder

object.mapView = someMapViewObject

mapView1 ist der Name des ivar in der Klasse, mapView ist der Name für die Getter / Setter-Methode (n).

Nyx0uf
quelle