AppController.h:
@interface AppController : NSObject
{
int fido;
}
@property (readonly, assign) int fido;
@end
import "AppController.h"
@implementation AppController
@synthesize fido;
...
@end
W tym momencie, zadeklarowałeś, że AppController ma metodę -fido
i zsyntetyzowałeś tę metodę. Nie ma metody. Dlaczego więc następująca "praca"?
- (id)init
{
if (self=[super init]) {
[self setValue:[NSNumber numberWithInt:5] forKey:@"fido"];
NSNumber *n = [self valueForKey:@"fido"];
NSLog(@"fido = %@", n);
}
return self;
}
(BTW: Poprawiłem swój -init wdrożenie prawidłowego wzorca)
To działa, ponieważ KVC następuje heurystycznej ustawić lub uzyskać wartość. Połączenie z numerem -setValue:forKey:
najpierw szuka -setFoo:
. Jeśli nie zostanie znaleziony, szuka zmiennej instancji foo
i ustawia ją bezpośrednio.
Należy pamiętać, że w przypadku zmiany zmiennej instancji fido
do _fido
, zestaw będzie działać, ale valueForKey
zwróci 0, gdyż wywołuje metodę zsyntetyzowany (ponieważ jestem na 64 bitów, @synthesize syntetyzuje zmienną fido
instancji Mylące, wiem.).
Jeśli zmienisz nazwę swojego ivar na bar
, a następnie użyjesz @synthesize foo=bar;
, kod zakończy się niepowodzeniem w środowisku wykonawczym.
Zobaczysz:
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
Możesz także użyć + (BOOL) accessInstanceVariablesDirectly {return NO; } aby wyeliminować to zachowanie KVC – sbooth
Dobra uwaga i dobry nawyk, aby się w to wciągnąć. Dzięki! – bbum
Świetna odpowiedź, dzięki. Powodem, dla którego zadałem to pytanie, było to, że jednym z głównych punktów tego rozdziału jest to, że KVC używa ustawiaczy i pobierających. Zakładałem, że to jedyny sposób, w jaki pracowali. Styl init jest stylem, którego używa w książce. Mówi, że klasy, do których zalicza klasy, nigdy nie wracają do zera, więc rezygnuje z kontroli dla uproszczenia. –