2013-02-08 8 views
7

Ich fange an zu lernen, wie einige iOS-Entwicklung in der Minute und ich habe derzeit die Apress IOS6 beginnen Buch, dass ich arbeite.iOS - Beginn iOS Tutorial - Unterstrich vor Variable?

In Kapitel zwei gibt es ein einfaches Tutorial, um zwei Tasten und eine Beschriftung zu zeigen. Wenn eine Taste gedrückt wird, wird auf dem Etikett angezeigt, welche Taste gedrückt wurde.

Ich habe das Tutorial abgeschlossen, aber es hat eine Frage aufgeworfen, auf die ich die Antwort nicht finden kann.

Das Lernprogramm verwendet ARC (automatische Referenzzählung) für den Fall, dass es einen Unterschied macht. Hier

ist der Code,

Die Header-Datei:

#import <UIKit/UIKit.h> 

@interface MTMViewController : UIViewController 


@property (weak, nonatomic) IBOutlet UILabel *statusLabel; 


- (IBAction)buttonPressed:(UIButton *)sender; 

@end 

Und die m-Datei:

#import "MTMViewController.h"  

@implementation MTMViewController 

- (IBAction)buttonPressed:(UIButton *)sender { 


    NSString *title = [sender titleForState:UIControlStateNormal]; 

    NSString *plainText = [NSString stringWithFormat:@"%@ button pressed.", title]; 

    statusLabel.text = plainText; 


} 

@end 

Die oben ist, wie es in dem Buch erscheint, aber wenn das zu tun Tutorial in Xcode konnte ich nicht mit der folgenden Zeile kompilieren:

statusLabel.text = plainText; 

Und stattdessen musste es ändern:

_statusLabel.text = plainText; 

Wenn ich diese den kompilierten Code gemacht und lief gut, ich versuchte herauszufinden, warum dies geschah durch das Tutorial geht zurück, um zu sehen, ob ich etwas verpasst, aber Ich habe nichts gesehen.

Kann mir jemand erklären, warum der Code im Buch nicht kompiliert wurde und warum ich den Unterstrich vor die Variable setzen musste? Ist das korrekt oder habe ich etwas falsch gemacht?

+1

Es gibt ein Konzept von "@ synthesize" zum Generieren von Getter und Setter. Wenn Sie diese Eigenschaft mit "@synthesize" deklarieren, können Sie direkt mit demselben Namen darauf zugreifen. Nur als Referenz. –

+0

@Jennis Ich würde das wirklich nicht empfehlen, da dies zu Verwirrung darüber führen wird, ob Sie auf die zugrunde liegende Variable oder über den generierten Getter/Setter zugreifen. Verschiedene Namen für verschiedene Zugriffsmöglichkeiten machen deutlich, was der Code tut und wie er begründet wird. Wenn Sie ältere Versionen von Xcode verwenden, bei denen '@ synthesize' für Eigenschaften obligatorisch ist, würde ich das Formular '@synthesize statusLabel = _statusLabel 'empfehlen. – WDUK

Antwort

11

Der Grund statusLabel.text = plainText; fehlgeschlagen ist, weil Sie nicht ordnungsgemäß auf die Eigenschaft zugegriffen haben. Um darauf durch die generierten Getter/Setter zugreifen zu können, müssen Sie ihm self. voranstellen, da die Eigenschaft (und ihre Setter/Getter) zur Instanz von self gehört. Also stattdessen wäre es self.statusLabel.text = plainText;

Der Grund _statusLabel funktioniert, weil dies die zugrunde liegende Variable ist, die den Wert für die Eigenschaft enthält. Sie umgehen die generierten Setter/Getter beim Zugriff auf die Variable auf diese Weise. Im Allgemeinen sollten Sie self.propertyName verwenden, da dies die Schlüsselwörter berücksichtigt, die Sie als Teil der Eigenschaftsdefinition angegeben haben (ein gutes Beispiel ist das Schlüsselwort atomic, da die generierten Setter und Getter einen @synchronized Block um die zugrunde liegende Instanz platzieren Variable).

Neueste Versionen von Xcode erstellen den Variablennamen mit einem vorangestellten Unterstrich, wenn Sie Ihre Eigenschaften nicht manuell synthetisieren (was eine OK-Sache ist, vorher Leute hatten manuell zu synthetisieren). Sie können Ihren eigenen zugrunde liegenden Variablennamen auf Wunsch mit @synthesize statusLabel = m_statusLabel definieren. Dies bedeutet, dass Sie mit m_statusLabel statt _statusLabel darauf zugreifen können. Sie sollten dies normalerweise nicht tun müssen, es sei denn, es besteht ein dringendes Bedürfnis danach; Apple schlägt vor, einen vorangestellten Unterstrich zu verwenden.

Sie sollten die zugrunde liegende Variable beim Initialisieren von Methoden und beim Aufheben der Zuweisung von Methoden verwenden, da die generierten Setter/Getter zu diesem Zeitpunkt im Code möglicherweise nicht vollständig sind.

+0

Ausgezeichnet, vielen Dank dafür, tolle Informationen. Ich vermute also, dass der Code im Buch in diesem Fall falsch ist und ich beim Lesen zukünftiger Kapitel im Buch die Datei "self.property" verwenden sollte. –

+1

Wenn der Code, den Sie gepostet haben, genau wie im Buch ist, dann ist das Buch falsch. Sie sollten 'self.statusLabel' verwenden. Ich kann sehen, wo sie hingefallen sind; Wenn ich erwähnte, dass Leute Eigenschaften manuell synthetisieren müssten, könnten Sie einfach '@synthesize statusLabel' verwenden. Dies würde eine zugrundeliegende Variable mit dem Namen 'statusLabel' erzeugen, was die Verwirrung für das ungeschulte Auge dessen verstärkt, ob Sie generierte Setter/Getter oder die zugrunde liegende Variable verwenden! – WDUK

+0

Eigentlich habe ich eine Sache ausgelassen, die nicht im Buch ist, aber im Quellcode mit dem Buch ist, das ist die Zeile @synthesize statusLabel; in der .m-Datei, was du da sagst. Ich bin immer noch ein wenig verwirrt, bin ich besser dran mit dem Self-Property-Ansatz oder dem [@] Synthesis-Property-Ansatz? –