Warum noch eine Nur-Lese-Eigenschaft ermöglichen, mit KVC Schreiben
-
19-09-2019 - |
Frage
Ich arbeite durch die "Key Value Coding" Kapitel in "Programmierung für Mac OS X". Ich habe eine Schnittstelle mit einem Schieberegler eingebaut und ein Etikett, beide gebunden an fido, ein int. Wenn ich die Eigenschaft für fido auf Read-only gesetzt, bewirkt, dass der Schieber bewegt noch das Etikett ändern Wert es ist. Ich hatte angenommen, dass ich für diese irgendeine Art von Fehler bekommen würde. Wenn die Eigenschaft nur lesbar ist, wie kommt es, dass der Schieber noch auf die Eigenschaft schreiben? Ich dachte, dass es hätte keine Setter erstellt und KVC nicht funktionieren würde. Danke.
Hier ist der Code verwende ich:
#import <Cocoa/Cocoa.h>
@interface AppController : NSObject
{
int fido;
}
@property (readonly, assign) int fido;
@end
#import "AppController.h"
@implementation AppController
@synthesize fido;
- (id)init
{
[super init];
[self setValue:[NSNumber numberWithInt:5] forKey:@"fido"];
NSNumber *n = [self valueForKey:@"fido"];
NSLog(@"fido = %@", n);
return self;
}
@end
alt text http://idisk.me.com/nevan/Public /Pictures/Skitch/Window-20091001-174352.png
Lösung
AppController.h:
@interface AppController : NSObject
{
int fido;
}
@property (readonly, assign) int fido;
@end
Import "AppController.h"
@implementation AppController
@synthesize fido;
...
@end
An diesem Punkt haben Sie erklärt, dass AppController eine -fido
Methode hat, und Sie haben das Verfahren synthetisiert. Es gibt keine -setFido:
Methode. Also, warum hat die folgende „Arbeit“?
- (id)init
{
if (self=[super init]) {
[self setValue:[NSNumber numberWithInt:5] forKey:@"fido"];
NSNumber *n = [self valueForKey:@"fido"];
NSLog(@"fido = %@", n);
}
return self;
}
(BTW: Ich reparierte Ihr -init das richtige Muster zu implementieren)
Das funktioniert, weil KVC ein heuristisches folgt setzen oder den Wert zu erhalten. Der Aufruf von -setValue:forKey:
erster Looks für -setFoo:
. Wenn nicht gefunden, es sieht dann für das Instanzvariable foo
und setzt sie direkt an.
Beachten Sie, wenn Sie die Instanz-Variable fido
_fido
ändern, wird das Set arbeiten, aber die valueForKey
0 zurück, da sie die synthetisierte Methode aufruft (da ich auf 64-Bit bin synthetisiert die @synthesize eine fido
Instanzvariable. verwirrend, ich weiß.).
Wenn Sie den Namen Ihres Ivar ändern sind bar
und dann @synthesize foo=bar;
verwenden, würde der Code zur Laufzeit fehlschlagen.
Sie werden sehen:
2009-10-01 08:59:58.081 dfkjdfkjfjkfd[24099:903] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<AppController 0x20000e700> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key fido.'
*** Call stack at first throw:
(
0 CoreFoundation 0x00007fff85b055a4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x00007fff85c5a0f3 objc_exception_throw + 45
2 CoreFoundation 0x00007fff85b5caf9 -[NSException raise] + 9
3 Foundation 0x00007fff814e14f5 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 434
(
0 CoreFoundation 0x00007fff85b055a4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x00007fff85c5a0f3 objc_exception_throw + 45
2 CoreFoundation 0x00007fff85b5caf9 -[NSException raise] + 9
3 Foundation 0x00007fff814e14f5 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 434
4 dfkjdfkjfjkfd 0x0000000100000d96 -[AppController init] + 130
Andere Tipps
Nur-Lese-Eigenschaft bedeutet, dass Compiler nicht generieren Sie für diese Eigenschaft Setter. Es ist immer noch legal es über KVO / KVC zu schreiben.
Die Compiler-Direktiven @property
und @synthesize
ist nur ein Kurz Möglichkeit, um die Methoden zum Erstellen zu erhalten und die betreffenden Variable gesetzt.
Die Setter-Methode erstellt wird setFido:
genannt, und die Getter-Methode wird nur genannt fido
.
Wenn Sie nur lesbar angeben, glaube ich, dass Sie einfach den Compiler erzählt die Setter-Methode nicht zu schaffen, sondern nur den Getter. Es spielt stellt keine Art von Barriere im Weg die Variable durch andere Mittel zu setzen.
(Hoffe, ich habe all das richtig verstanden habe. Viel Glück!)