Question

Je travaille par la « valeur clé de codage » chapitre « Programmation pour Mac OS X ». Je l'ai construit une interface avec un curseur et une étiquette, à la fois lié à fido, un int. Si je mets la propriété pour fido à lecture seule, déplacer le curseur provoque toujours l'étiquette pour changer sa valeur. Je l'avais supposé que j'obtenir une sorte d'erreur pour cela. Si la propriété est en lecture seule, comment se fait le curseur peut encore écrire à la propriété? Je pensais qu'il aurait pas créé setters et KVC ne fonctionnerait pas. Merci.

Voici le code que je utilise:

#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 texte http://idisk.me.com/nevan/Public /Pictures/Skitch/Window-20091001-174352.png

Était-ce utile?

La solution

AppController.h:

@interface AppController : NSObject
{
        int fido;
}

@property (readonly, assign) int fido;
@end

import "AppController.h"

@implementation AppController
@synthesize fido;
...
@end

À ce stade, vous avez déclaré que AppController a une méthode -fido et vous avez synthétisé cette méthode. Il n'y a pas de méthode de -setFido:. Alors, pourquoi le « travail » qui suit?

- (id)init
{
        if (self=[super init]) {
            [self setValue:[NSNumber numberWithInt:5] forKey:@"fido"];
            NSNumber *n = [self valueForKey:@"fido"];
            NSLog(@"fido = %@", n);
        }
        return self;
}

(BTW: je fixe votre -init pour mettre en œuvre le modèle correct)

Cela fonctionne parce que KVC suit une heuristique pour définir ou obtenir la valeur. L'appel à -setValue:forKey: recherche d'abord -setFoo:. Si non trouvé, il recherche alors l'instance foo variable et fixe directement.

Notez que si vous changez l'instance fido variable _fido, l'ensemble fonctionnera, mais le valueForKey retourne 0 car il appelle la méthode de synthèse (depuis que je suis sur 64 bits, la @synthesize synthétise une variable d'instance de fido. Confondre, je sais.).

Si vous deviez changer le nom de votre Ivar à bar puis utilisez @synthesize foo=bar;, le code échoue lors de l'exécution.

Vous allez voir:

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

Autres conseils

Avoir la propriété readonly signifie que le compilateur ne vous générer setter pour cette propriété. Il est toujours légal d'écrire via KVO / KVC.

Les directives du compilateur @property et @synthesize sont des moyens juste sténographie pour créer les méthodes pour obtenir et définir la variable en question.

La méthode setter créé est nommé setFido:, et la méthode de lecture est vient d'être nommée fido.

Lorsque vous spécifiez lecture seule, je crois que le compilateur dit simplement de ne pas créer la méthode setter, mais seulement le getter. Il ne met pas toute sorte de barrière de la manière de définir la variable par d'autres moyens.

(espoir que j'ai tout ce droit. Bonne chance!)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top