2012-04-26 7 views
45

Gibt es einen Unterschied zwischen der Verwendung des Unterstrichs und der Verwendung des Schlüsselwortes self in Objective-C beim Aufruf einer @property?Unterschied zwischen _ und selbst. in Objective-C

Property Erklärung:

@property (weak, nonatomic) NSString *myString; 

Aufruf @synthesize auf dem Grundstück:

@synthesize myString = _myString; 

Gibt es einen Unterschied, ob ich es in meinem Code verwenden? Wann? Im Getter/Setter?

self.myString = @"test"; 
_myString = @"test"; 
+0

'self' ist ein Symbol. '_' ist ein Zeichen in einigen Symbolen. 'myString' und' _myString' sind zwei verschiedene Symbole, die zufällig zusammenhängen, nicht wegen der Schreibweise, sondern weil sie im gleichen '@ syntheize' benannt sind. –

+0

Versuchen Sie, die folgende Antwort: http://stackoverflow.com/questions/5170631/what-does-synthesize-window-window-do – Peres

+2

Überprüfen Sie, ob @ Jonathan Antwort auf diese früheren SO Frage hilft http: // Stackoverflow .com/questions/5466496/why-rename-synthesed-properties-in-ios-mit-führenden-unterstrichen – visakh7

Antwort

68

self.myString = @"test"; entspricht genau dem Schreiben [self setMyString:@"test"];. Beide rufen eine Methode auf.

Sie hätten diese Methode selbst schreiben können. Es könnte wie folgt aussehen:

- (void)setMyString:(NSString*)newString 
{ 
    _myString = newString; 
} 

Weil Sie @synthesize verwendet, die Sie nicht wirklich diese Methode plagen schreiben müssen, können Sie einfach der Compiler erlauben es Ihnen zu schreiben.

Also, wenn man sich diese Methode anschaut, sieht es so aus, als ob sie aufgerufen wird, genau das Gleiche zu tun, als nur einen Wert der Instanzvariablen zuzuweisen, richtig? Nun, es ist nicht so einfach.

Erstens könnten Sie Ihre eigene Setter-Methode schreiben. Wenn Sie dies tun, wird Ihre Methode aufgerufen, und sie kann alle möglichen zusätzlichen Dinge tun und die Variable setzen. In diesem Fall würde die Verwendung von self.myString = Ihre Methode aufrufen, würde aber _myString = nicht tun, und somit würden andere Funktionen verwendet werden.

Zweitens, wenn Sie jemals Key Value Observing verwenden, macht der Compiler einige sehr clevere Tricks. Hinter den Kulissen unterklassifiziert es Ihre Klasse und setzt Ihre Setter-Methode außer Kraft (ob Sie selbst oder eine durch Synthetisieren erzeugte), um die Aufrufe an willChangeValueForKey:, die für das Arbeiten mit Schlüsselwertbeobachtung benötigt werden, durchzuführen. Sie müssen nicht wissen, wie das funktioniert (obwohl es ziemlich interessant ist, wenn Sie etwas vor dem Schlafengehen lesen wollen!), Aber Sie müssen wissen, dass Sie, wenn Sie möchten, dass das Schlüsselwert-Beobachten automatisch funktioniert, Setter-Methoden verwenden müssen.

Drittens, rufen Sie die Setter-Methode, auch wenn Sie auf synthetisieren, um einen zu schreiben gibt Ihnen Flexibilität für die Zukunft. Vielleicht möchten Sie etwas mehr tun, wenn ein Wert geändert wird, und an dem Punkt, an dem Sie feststellen, dass Sie dies tun möchten, können Sie manuell eine Setter-Methode schreiben - wenn Sie es gewohnt sind, immer self.myString = zu verwenden müssen Sie den Rest Ihres Codes ändern, um mit dem Aufruf der neuen Methode zu beginnen!

Viertens gilt das Gleiche für Unterklassen. Wenn jemand anders Ihren Code unterklassifizieren würde, könnten Sie ihn überschreiben, wenn Sie die Setter verwenden, um die Funktionalität anzupassen.

Jedes Mal, wenn Sie direkt auf die Instanzvariable zugreifen, bieten Sie zu diesem Zeitpunkt explizit keine Möglichkeit für zusätzliche Funktionen. Da Sie oder jemand anderes diese Funktionalität in Zukunft nutzen möchten, lohnt es sich, die Setter die ganze Zeit zu verwenden, es sei denn, es gibt einen guten Grund, dies nicht zu tun.

+0

Beachten Sie, dass ich die Speicherverwaltungsimplikationen nicht erwähnt habe. Wenn Sie ARC verwenden, sind sie in diesem Fall viel weniger relevant, also habe ich sie übersprungen. –

+0

Gute Erklärung :) – iTag

+0

Übrigens, in Bezug auf den ersten Satz ... Dies ist 99% der Zeit, aber wenn Sie einen benutzerdefinierten Setter haben (angegeben mit 'Setter =' in der Eigenschaftserklärung), dann die beiden Formen sind nicht genau gleichwertig. –

8

Sie sind richtig - die erste Version (self.myString) ruft die synthetisierten Getter/Setter und die zweite Version Zugriff auf die private Variable direkt.

Es sieht so aus, als ob Sie ARC verwenden, also macht es in diesem Fall keinen großen Unterschied. Wenn Sie jedoch ARC nicht verwenden, kann dies einen Unterschied machen, da die direkte Zuweisung an das private Member nicht die automatische Retain/Release- oder Kopier/Release-Logik auslöst, die für Sie mithilfe von synthesize generiert wird.

+0

Sie sind zwei verschiedene Symbole. Man könnte "Aardvark" und das andere "Zebra" sein und immer noch die Variable-Setter/Getter-Beziehung haben. –

+0

@Hot Licks - Sie sind richtig, dass die Namen irrelevant sind, aber als ich die Frage las, denke ich, er fragte sich, was der praktische Unterschied zwischen der Verwendung der synthetisierten Eigenschaft gegenüber der Verwendung der Member-Variable ist. –

+0

@EricPetroelje - Ja, genau das, was ich gefragt habe. Vielen Dank! – Kuba

3

Die _ (Unterstrich) ist einfach eine Konvention, wie in this question erklärt.

Wenn Sie keinen Eigenschaftenzugriff mit self. voranstellen, greifen Sie direkt auf die zugrunde liegende Variable zu, wie in einem c struct. Im Allgemeinen sollten Sie dies nur in Ihren init-Methoden und in benutzerdefinierten Eigenschaftenaccessoren tun. Dies ermöglicht, dass Dinge wie berechnete Eigenschaften und KVC wie vorgesehen funktionieren.