Perché una proprietà di sola lettura consentono ancora iscritto con KVC
-
19-09-2019 - |
Domanda
Sto lavorando attraverso il capitolo "Chiave Valore Codifica" in "di programmazione per Mac OS X". Ho costruito un'interfaccia con un cursore e un'etichetta, sia legato a Fido, un int. Se ho impostato la proprietà per Fido a sola lettura, spostando il cursore ancora provoca l'etichetta per cambiare il suo valore. Avevo pensato che avrei avuto un qualche tipo di errore per questo. Se la proprietà è di sola lettura, come mai il dispositivo di scorrimento può ancora scrivere alla proprietà? Ho pensato che avrebbe avuto setter create, e KVC non avrebbe funzionato. Grazie.
Ecco il codice che sto usando:
#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
Soluzione
AppController.h:
@interface AppController : NSObject
{
int fido;
}
@property (readonly, assign) int fido;
@end
Importa "AppController.h"
@implementation AppController
@synthesize fido;
...
@end
A questo punto, avete dichiarato che AppController ha un metodo -fido
e hai sintetizzato quel metodo. Non esiste un metodo -setFido:
. Allora, perché fa il seguente "lavoro"?
- (id)init
{
if (self=[super init]) {
[self setValue:[NSNumber numberWithInt:5] forKey:@"fido"];
NSNumber *n = [self valueForKey:@"fido"];
NSLog(@"fido = %@", n);
}
return self;
}
(a proposito: ho fissato il vostro -init per implementare il modello corretto)
Questo funziona perché KVC segue un euristica per impostare o ottenere il valore. La chiamata a -setValue:forKey:
primi sguardi per -setFoo:
. Se non viene trovato, sembra quindi per l'istanza foo
variabile e imposta direttamente.
Si noti che se si modifica la fido
variabile di istanza al _fido
, il set funzionerà, ma il valueForKey
tornerà 0 come viene chiamato il metodo sintetizzato (dato che sono a 64 bit, il @synthesize sintetizza una variabile di istanza fido
. Confondere, lo so.).
Se si dovesse cambiare il nome del tuo Ivar per bar
e quindi utilizzare @synthesize foo=bar;
, il codice sarebbe fallire in fase di esecuzione.
Vedrai:
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
Altri suggerimenti
Avendo proprietà di sola lettura significa che compilatore non genererà si setter per la proprietà. E 'ancora legale di scrivere ad esso attraverso KVO / KVC.
L'direttive del compilatore @property
e @synthesize
sono modi solo stenografia per creare i metodi per ottenere e impostare la variabile in questione.
Il metodo setter creato si chiama setFido:
, e il metodo getter viene semplicemente chiamata fido
.
Quando si specifica in sola lettura, credo che semplicemente dice al compilatore di non creare il metodo setter, ma solo il getter. Non pone alcun tipo di barriera nel modo di impostazione della variabile con altri mezzi.
(speranza Ho tutto il diritto. Buona fortuna!)