5

「Mac OS X のプログラミング」の「キー値のコーディング」の章に取り組んでいます。スライダーとラベルを備えたインターフェイスを作成しました。どちらも int である fido にバインドされています。fido のプロパティを読み取り専用に設定した場合、スライダーを移動すると、ラベルの値が変更されます。これで何らかのエラーが発生するだろうと想定していました。プロパティが読み取り専用の場合、スライダーがプロパティに書き込みできるのはなぜですか? セッターが作成されず、KVC が機能しないと思いました。ありがとう。

私が使用しているコードは次のとおりです。

#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

代替テキスト http://idisk.me.com/nevan/Public/Pictures/Skitch/Window-20091001-174352.png

4

3 に答える 3

16

AppController.h:

@interface AppController : NSObject
{
        int fido;
}

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

「AppController.h」をインポート

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

この時点で、AppController に-fidoメソッドがあることが宣言され、そのメソッドが合成されました。方法はありません-setFido:。では、なぜ次の「動作」するのでしょうか。

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

(ところで:正しいパターンを実装するために -init を修正しました)

これが機能するのは、KVC がヒューリスティックに従って値を設定または取得するためです。への呼び出しは、-setValue:forKey:最初に を探し-setFoo:ます。見つからない場合は、インスタンス変数fooを探して直接設定します。

インスタンス変数fidoを に変更する_fidoと、セットは機能 valueForKeyしますが、合成されたメソッドを呼び出すと 0 が返されることに注意してください (私は 64 ビットを使用しているため、@synthesize はfidoインスタンス変数を合成します。紛らわしいことはわかっています)。

ivar の名前を に変更してからbarを使用する@synthesize foo=bar;と、コードは実行時に失敗します。

わかるでしょ:

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
于 2009-10-01T16:00:38.610 に答える
1

コンパイラ ディレクティブ@property@synthesizeは、問題の変数を取得および設定するメソッドを作成する簡単な方法です。

作成されたセッター メソッドは という名前setFido:で、ゲッター メソッドは単に という名前fidoです。

readonly を指定すると、setter メソッドを作成せず、getter メソッドのみを作成するようにコンパイラに指示するだけだと思います。他の手段で変数を設定する方法に、いかなる種類の障壁も置きません。

(私はすべての権利を持っていることを願っています。頑張ってください!)

于 2009-10-01T15:34:44.387 に答える
1

読み取り専用プロパティを持つということは、コンパイラがそのプロパティのセッターを生成しないことを意味します。KVO/KVC 経由で書き込むことは引き続き合法です。

于 2009-10-01T08:50:34.903 に答える