Frage

sagen, ich habe die folgende:

@interface MyClass : NSObject { NSString* _foobar; }
@property (nonatomic, retain) NSString* foobar;
@end

@implementation MyClass
@dynamic foobar;
- (void) setFoobar:(NSString*)fbSet; { [_foobar release]; _foobar = [fbSet retain]; }
- (NSString*) foobar; { return _foobar; }
@end

Dann:

MyClass* mcInst = [[[MyClass alloc] init] autorelease];
NSLog(@"I set 'foobar' to '%@'", (mcInst.foobar = @"BAZ!"));

an dem Rückgabewert von -[MyClass setFoobar:] Sehen, könnte man hier davon aus, dass diese Linie I set 'foobar' to '' drucken würde, weil die Zuordnung nichts zurück erscheint.

Aber - Gott sei Dank - diese Zuordnung wirkt wie erwartet, und der Code druckt I set 'foobar' to 'BAZ!'. Leider das fühlt sich an wie ein Widerspruch, weil der Rückgabewert der geltend gemachte Setter täuscht über die Tatsache, dass die Zuordnung der Wert zugewiesen zurückgibt. Zuerst dachte ich, dass mcInst.foobar = @"BAZ!"; macht zwei Anrufe stattdessen ein Block: zuerst die Setter und dann der Getter den Rückgabewert zu sammeln. Doch mit NSLog fordert die Setter und Getter-Methoden instrumentiert beweist dies nicht der Fall ist.

War es hilfreich?

Lösung

Schnell Zusammenfassung:

Die schnelle Antwort ist, dass es kein Widerspruch, denn das Ergebnis des Ausdrucks:

(mcInst.foobar = @"BAZ!")

ist eigentlich @"BAZ!" und nicht mcInst.foobar.

Weitere Einzelheiten finden Sie unten, aber es könnte helfen, die folgenden Änderungen an Ihrem setFoobar Verfahren zu beachten:

- (void) setFoobar:(NSString*)fbSet
{
    [_foobar release];
    _foobar = [[NSString stringWithFormat:@"HELLO_%@", fbSet] retain];
}

Mit diesem Code vorhanden, der Wert der foobar Eigenschaft geändert wird, während es gesetzt wird, , aber Ihre Code-Zeile noch den Wert anzuzeigen ‚BAZ!‘ .

Details:

Wie von newacct Ihr NSLog Code funktioniert, weil Sie den Zuweisungsoperator (=) verwenden, die einige sehr spezifische Verhalten in der C-Sprache hat (die Objective-C basiert auf)

In C, können Sie wie folgt vor:

x = y = z = 42;

und alle Variablen, x, y und z den Wert 42 halten.

Der Compiler behandelt dieses Verhalten durch eine temporäre Variable mit (*). Im Wesentlichen, was hinter den Kulissen geschieht etwas wie folgt aussieht:

tempVar = 42;
z = tempVar;
y = tempVar;
x = tempVar;

In der gleichen Richtung, können Sie Folgendes tun:

SomeFunction(x = 42);

Diese Codezeile wird der Wert von 42 in x kopieren und dann SomeFunction mit einem Argument von 42. Hinter den Kulissen zu nennen, sieht es wie folgt aus:

tempVar = 42;
x = tempVar;
SomeFunction(tempVar);

Nun, in Objective-C, Logging-Linie wird wie folgt behandelt:

tempVar = @"BAZ!";
[mcInst setFooBar:tempVar];
NSLog(@"I set 'foobar' to '%@'", tempVar);

(*) zur Kenntnis, dass die Verwendung eines „temporaray Variable“ Ich beschreibe sollte das Konzept zu veranschaulichen und nicht wirklich widerspiegelt, was jeder gegebener Compiler tut tatsächlich unter der Haube. Diese Art der Implementierung Detail ist an die Programmierer auf, die den Compiler zu schreiben, und jeder kann etwas anderes tun. Das Endergebnis ist jedoch das gleiche.

Andere Tipps

Es gibt keine Notwendigkeit, einen Getter zu nennen - es muss der Wert auf der gleichen Linie genau dort zugeordnet ist. Sie können daran denken, wie an [mcInst setFoobar:@"BAZ!"], @"BAZ!" erweitert.

in C, Zuordnung ist ein Ausdruck, der auswertet, um den zugewiesenen Wert

Dies ist wegen der Art und Weise des C Zuweisungsoperator arbeitet. Wie in dem ANSI-C-Standard beschrieben:

"ein Zuweisungsoperator speichert ein Wert in dem Objekt bezeichnet durch der linke Operand. Ein Zuweisungsausdruck den Wert der linken Operanden nach der Zuweisung ... "

Ihr Zuweisungsausdruck ist mcInst.foobar = @"BAZ!". Es scheint mir sinnvoll zu machen, dass, obwohl die Zuordnung funktioniert, indem die gleiche wie bei C ein Verfahren auf mcInst das Verhalten Aufruf Der Wert des Zuweisungsausdrucks ist der linke Operand nach der Zuweisung (@"BAZ!") so dieser Wert auf die übergeben wird NSLog Funktion.

Dies ist das gleiche Verhalten, das Ihnen eine initialiser im Stil if (self = [super init]) schreiben.

P. S. Es ist eine faire Frage zu fragen, warum würde der Compiler den Setter auf der Eigenschaft aufrufen, wenn der Wert zu zuweisen und die Getter nicht aufrufen, wenn der Wert von mcInst.foobar danach verwenden. Ich würde sagen, dass es einfach der Getter angenommen wird den gleichen Wert zurück, die nur auf die Eigenschaft zugeordnet wurde und deshalb wird der Getter nicht genannt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top