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

È stato utile?

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!)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top