2011-11-19 8 views
8

だから、私はすでにKVCとプロパティの違いは何ですか?

のObjective-C 2.0のドット構文とキー値コーディングを指摘する文書をよく読んできたが直交した技術です。ドットシンタックスを使用するかどうかにかかわらず、キー値コーディングを使用できます.KVCを使用するかどうかにかかわらず、ドット構文を使用できます。ただし、どちらも「ドット構文」を使用します。キー値コーディングの場合、構文はキーパス内の要素を区切るために使用されます。ドット構文を使用してプロパティにアクセスするときは、レシーバの標準アクセサメソッドを呼び出すことを覚えておくことが重要です。

これは、2つの違いがあると思われる例を示しています。しかし、私はまだKVCとプロパティアクセサメソッドの違いは何ですか?彼らは同じではありませんか?そして、setValue:forKeyPath:と単純アクセサの呼び出し点を区別するにはどうしたらいいですか?

答えて

14

しかし、私はまだ取得していない、KVCとプロパティアクセサメソッドの違いは何ですか?

KVCは、プロパティアクセサメソッドを呼び出す方法、またはプロパティにアクセスする方法です。

「その他のアクセス」とはどういう意味ですか? KVCの目的のために、アクセサメソッドを持たないインスタンス変数は、非公式のプロパティとしてカウントされます。一致するアクセサのペアが見つからない場合は、インスタンス変数の値を直接取得または設定します。 (これは現代のコードでは使用する価値がありません。他の場所にアクセスしようとするものについては@propertyと宣言し、逆に公共の財産でないものにはKVCを使用しないでください)

プロパティアクセサメソッドは、KVCが存在する場合に呼び出すものです(KVCとすべての正常なプログラマの両方が直接ivarアクセス​​を行うことが好ましい)。アクセサは、合成されたアクセサが行うようにインスタンス変数を取得または設定したり、他のストレージにアクセスすることができます。

アクセサは実装であり、プロパティはインターフェイスであり、KVCはそれらを使用する1つの方法です。

setValue:forKeyPath:と単純アクセサの呼び出し点を区別するにはどうすればよいですか?

キーパスは文字列ですが、プロパティアクセス式は式です。コンパイラはプロパティアクセス式を評価し、それを1つまたは複数のObjective-Cメッセージに変換しますが、キーパスは実行時にKVCによって評価されます。

だから、あなたはキーのパスを使用する場合:

[someObject setValue:theValue forKeyPath:@"foo.bar.baz"]; 

を(1)それは文字列リテラル構文@"…"ことで、この場合に示されているように、文字列だし、(2ので、あなたはそれがキーパスを知っています)を評価するには、キーパス文字列をsetValue:forKeyPath:に渡しています。

キーパスを使用すると、KVCを使用して名前付きプロパティにアクセスしています。それはあなたのために関連アクセサメッセージを送信します。

、プロパティ・アクセス式を使用する場合:

someObject.foo.bar.baz = theValue; 

をあなたは文字列でプロパティを特定していないので、それがプロパティアクセス表現を知っています。あなた自身のコードで自分自身にアクセスしています(アクセサーメッセージを送信しています)。

KVCを使用する理由はあまりありません。作成者/コンパイル時にプロパティを知っているときは、プロパティーアクセス式またはメッセージ式([[[someObject foo] bar] setBaz:theValue])を使用して、@propertyを宣言し、プロパティに直接アクセスすることをお勧めします。 KVCを使用する時間は、実行時までアクセスしたいプロパティがわからないときです。これはまれです。主にKVO、ココアバインディング、Core Animationの部分のビルディングブロック技術です。

ほとんどの場合、あなたは自分でプロパティにアクセスしたいだけです。

+4

**「実行時までアクセスしたいプロパティがわからないときはKVCを使用する時間です」**は私が探していたものです。 – km3h

+0

それは私のために本当に役に立ちました。私は気にしていました** KVCを使用する時間は、実行時までアクセスしたいプロパティがわからないときです**これは理由かもしれませんが、わかりませんでした。あなたは私の考えを確信してくれました。 –

+0

ピーターはあなたの状態です "、逆に公共の財産でないものにはKVCを使用しないでください。"プロパティーが読み取り専用として宣言され、実装で読み書き可能と宣言された場合、KVCはそのプロパティに恥知らずに書き込むことになります。これをブロックする方法はありませんか?試みました(BOOL)accessInstanceVariablesDirectly { –

2

キー値コーディングでは、プロパティの文字列名を使用してコードを通じてプロパティの値を設定および取得できます。たとえば、NSString型のfooという名前のプロパティがある場合:

[self setValue:@"mystring" forKey:@"foo"]; 

// read the value by key 
NSString *s = [self valueForKey:@"foo"]; 

ドットシンタックスはシンタックスシュガーをコンパイルします。個人的な好み(一部は同意しないと - 罰金)として、私は、ドット構文を使用していないが、私はまだKVCを使用します。

[myObj setFoo: @"someString"] 

等しい:

myObj.foo = @"someString"; 

彼らは直交し、異なる概念ですが、両方ともあなたがプロパティと対話する方法を扱います。

最後に、プロパティ構文について言及します。さらに別の直交概念であるが、プロパティを扱うことに関連する。

objective-cでは、慣例が重要です。それらに従う。今

- (NSString*)foo 
{ 
    return _foo; // defined as (NSString*)_foo in header 
} 

- (void) setFoo: (NSString*)foo 
{ 
    if (foo == _foo) 
     return; 

    NSString* curr = _foo; 

    _foo = [foo retain]; 
    [curr release];  
} 

、そのようなことを毎回書きたい:プロパティは、割り当てのための取得および設定[名前]のプロパティの名前です。 .Mに続いて

@property (retain) NSString *foo; 

ヘッダーは次のようになりますので、@property構文を入力して手書きのプロパティアクセサの同等だ

@synthesize foo; 

を。それはプロパティをどのように属性に基づいてプロパティコードを展開するコンパイラ構文の砂糖です。

ドキュメント:

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html