16

CocoaのKey-Valueコーディング(KVC)メカニズムをもう少しよく理解しようとしています。AppleのKey-Valueプログラミングガイドを読みましたが、特定のKVCメソッドがキーを検索する方法についてまだ少し混乱しています。特に、mutableArrayValueForKey :。

valueForKey:以下では、 KVCの「ゲッター」が機能することをどのように理解しているかを説明します。次に、mutableArrayValueForKeyに関する質問に行きます。


7つの異なる「ゲッター」KVCメソッドがあります。

- (id)valueForKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;
- (NSMutableArray *)mutableArrayValueForKeyPath:(NSString *)keyPath;
- (NSMutableSet *)mutableSetValueForKey:(NSString *)key;
- (NSMutableSet *)mutableSetValueForKeyPath:(NSString *)keyPath;

プロパティ(myKeyという名前)内の値を検索する場合、AppleのドキュメントにはvalueForKey:が次のように検索されると記載されています。

  1. 受信機内で、、、および(この順序で)-getMyKey試行し-myKeyます-isMyKey
  2. 見つからない場合は、次の順序付けられたto-manyゲッター(NSArray)を試行します。

    // Required:
    - (NSUInteger)countOfMyKey;
    
    // Requires At Least One:
    - (id)objectInMyKeyAtIndex:(NSUInteger)index;
    - (NSArray *)myKeyAtIndexes:(NSIndexSet *)indexes;
    
    // Optional (improves performance):
    - (void)getMyKey:(KeyClass **)buffer range:(NSRange)inRange;
    
  3. 次に、これらの順序付けられていない多数のゲッター(NSSet)を試行します。

    - (NSUInteger)countOfMyKey;
    - (NSEnumerator *)enumeratorOfMyKey;
    - (KeyClass *)memberOfMyKey:(KeyClass *)anObject;
    
  4. 次に、、、、、の順序でがYES返されると仮定して、インスタンス変数に直接アクセスしようとします。accessInstanceVariablesDirectly_myKey_isMyKeymyKeyisMyKey

  5. 最後に、それはあきらめて、受信クラスの- (id)valueForUndefinedKey:(NSString *)keyメソッドを呼び出します。通常、ここでエラーが発生します。


私の質問は、mutableArrayValueForKeyの検索順序パターンは何ですか?

Appleのドキュメントはこれを述べています

順序付けられたコレクションのアクセサー検索パターン

mutableArrayValueForKey:のデフォルトの検索パターンは次のとおりです。

受信者のクラスは、名前がパターン-insertObject:inAtIndex:および-removeObjectFromAtIndex:(それぞれ、NSMutableArrayプリミティブメソッドinsertObject:atIndex:およびremoveObjectAtIndex:に対応)に一致するメソッドのペア、またはパターン-insert:atIndexesに一致するメソッドを検索します。 :および-removeAtIndexes:(NSMutableArrayinsertObjects:atIndexes:およびremoveObjectsAtIndexes:メソッドに対応)。少なくとも1つの挿入メソッドと少なくとも1つの削除メソッドが見つかった場合、コレクションプロキシオブジェクトに送信される各NSMutableArrayメッセージは、-insertObject:inAtIndex:、-removeObjectFromAtIndex:、-insert:atIndexes:、および-removeAtIndexes:メッセージの組み合わせになります。 mutableArrayValueForKeyの元の受信者に送信されます:。...等...

「セッター」のような方法について話しているので、これは私には意味がありません。 mutableArrayValueForKey:NSMutableArrayを返します。上記のすべてのメソッドはvoidを返し、NSMutableArrayを編集するために使用されますが、取得するためには使用されません。例:

- (void)insertMyKey:(KeyClass *)keyObject inMyKeyAtIndex:(NSUInteger)index;
- (void)removeObjectFromMyKeyAtIndex:(NSUInteger)index;

Appleが彼らのドキュメントで何を言おうとしているのか、あるいはこれがおそらくエラーであるのかどうか、何か考えはありますか?

私の理論では、KVC値を取得するために検索する場合mutableArrayValueForKey:と同様のパスをたどる可能性があります。valueForKey:それが実際にどのような道なのかよくわかりません。

あなたが提供できるどんな助けにも感謝します!:)

4

1 に答える 1

23

NSMutableArray呼び出しから返されるのmutableArrayValueForKey:は、実際にはプライベートサブクラスであり、そのサブクラスは、、、などのNSMutableArray通常の配列メソッドをオーバーライドし、配列が取得されたオブジェクトの対応するKVCメソッドを呼び出します。これは基本的に、オブジェクトの対多の関係を操作するためのプロキシとして機能し、自分で作成したり戻したりすることを心配する必要はありません。使用法の簡単な例:-count-objectAtIndex:-insertObject:atIndex:

Playlist* aPlaylist;
Track* aTrack;
NSMutableArray* mutableTracks = [aPlaylist mutableArrayValueForKey:@"tracks"];
[mutableTracks insertObject:aTrack atIndex:0];

このコードは、プレイリストの先頭にトラックを追加します。プレイリストクラスがその「トラック」関係にKVCメソッドを実装している場合、可変配列でメソッドを呼び出すと、基になるオブジェクトで適切なメソッドが呼び出されます。したがって、この例では、配列を呼び出すinsertObject:atIndex:と、配列がinsertObjectInTracks:atIndex:プレイリストオブジェクトを呼び出し、トラックがプレイリストのトラックの配列に追加されます。

さて、この例では、もちろん直接呼び出すこともできますが、代わりinsertObjectInTracks:atIndex:に使用することで得られるいくつかの利点があります。mutableArrayValueForKey:

  • 配列ラッパーは、基盤となるKVCメソッドの実装の詳細を非表示にします。メソッドのリスト全体を実装することは、KVCに準拠している必要はありません。プレイリストクラスはとを実装するだけ-tracks-setTracks:、上記のコードは引き続き機能します。この場合、を呼び出す代わりにinsertObjectInTracks:atIndex:、可変配列プロキシは、オブジェクトが最初に挿入された新しい配列を作成setTracks:し、Playlistオブジェクトを呼び出すだけです。これは明らかに効率が悪いため、通常、KVCメソッドの完全なリストを実装することをお勧めします。
  • キーの定数文字列の代わりに変数がある場合、を使用mutableArrayValueForKey:すると、呼び出す必要のあるメソッドの正確な名前を知らなくても、関係を操作できます。オブジェクトが使用しているキーに対してKVCに準拠している限り、すべてが「正常に機能」します。
  • また、NSMutableArrayそれ自体が実装する任意のメソッドを使用できるため、たとえば、KVCのものを処理するために特別なバージョンを書き直すことなく、オブジェクトの配列を検索したり、配列を並べ替えたりするメソッドを使用できます。
于 2010-02-19T07:33:08.090 に答える