3

カスタム クラス ( MyClass) 配列をプログラムで配列コントローラー ( NSArrayController) にバインドし、その内容を別の配列 ( modelArray) にバインドしたいと考えています。MyClassのように、配列の内容を表示しますNSTableView

私の問題は、可変配列のメソッドが呼び出されるようにこのバインディングを作成する方法、つまりメソッドです

-(void) insertObject:(id)object inContentAtIndex:(NSUInteger)index
-(void) removeObjectFromContent:(id) object

(1)この方法でバインドすると、上記のメソッドが呼び出されますが、コントローラーのコンテンツはmodelArray(明らかに)バインドされなくなります

[myArrayController bind:@"contentArray" toObject:myClassInstance withKeyPath:@"content" options:nil];

(2) これらの方法でバインドすると、メソッドsetContent:とメソッドのみcontentが呼び出され、変更可能なメソッドは呼び出されません。setContent:また、これらのメソッド (および)を削除しようとしましたcontentが、例外が発生するだけですsetValue:forUndefinedKey:

[myClassInstance bind:@"content" toObject:myArrayController withKeyPath:@"arrangedObjects" options:nil];

また

[myClassInstance bind:@"content" toObject:myArrayController withKeyPath:@"content" options:nil];

配列コントローラーにバインドされているときに行が追加されるたびに、テーブルの配列全体が再設定されるとは思わないので、同じ種類のバインドが必要です。

4

1 に答える 1

2

あなたが抱えている問題は、配列値がキー値コーディングによってどのように扱われるかに関係しています。KVC には特定の型付けの概念がないため、KVC を介して配列値にアクセスする場合、返された配列が可変であることを知る方法がありません。最悪の事態 (つまり、配列が不変) を想定する必要があります。通常、これを処理する方法は、NSMutableArray のように機能するプロキシ オブジェクトを使用することですが、舞台裏では、想定された不変配列を取得し、変更可能なコピーを作成し、コピーを変更してから、セッターを使用してすべてをプッシュします。(これはあなたが見ている動作です。配列全体がその場で変更されるのではなく、置き換えられています。)

この機能を制御するメソッドは- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key. そのメソッドでは多くのことが行われている可能性があります。このメソッドのヘッダー コメントを以下に貼り付けて、完全なストーリーを説明しますが、簡単に言うと、NSArrayController で変更可能な配列を適切に変更したい場合は、最も簡単な方法は、modelArrayプロパティを販売するクラスにこのオーバーライドを追加することです。

- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key
{
    if ([@"modelArray" isEqual: key])
    {
        // We know this is mutable, even if KVC doesn't!
        return self.modelArray;
    }
    return [super mutableArrayValueForKey:key];
}

より長い話は、コレクションの変更を処理する方法を見つけようとするときに、KVC が探す一連のものがあるということです。詳細については、 を参照してNSKeyValueCoding.hください。へのコメントですmutableArrayValueForKey:

順序付けられた対多関係を識別するキーを指定すると、関連オブジェクトへの読み取り/書き込みアクセスを提供する可変配列を返します。可変配列に追加されたオブジェクトはレシーバーに関連付けられ、可変配列から削除されたオブジェクトは関連付けられなくなります。

このメソッドのデフォルトの実装は、-valueForKey: と同じ単純なアクセサー メソッドと配列アクセサー メソッドを認識し、同じ直接インスタンス変数アクセス ポリシーに従いますが、-valueForKey: の不変コレクションではなく、常に可変コレクション プロキシ オブジェクトを返します。戻ってきます。また:

  1. -insertObject:in<Key>AtIndex:パターンand -removeObjectFrom<Key>AtIndex:(NSMutableArray クラスで定義された 2 つの最も基本的なメソッドに対応) および (Mac OS 10.4 で導入) および ( -insert<Key>:atIndexes:and に-remove<Key>AtIndexes:対応) に一致する名前を持つメソッドをレシーバーのクラスから検索します。少なくとも 1 つの挿入メソッドと少なくとも 1 つの削除メソッドが見つかった場合、コレクション プロキシ オブジェクトに送信される各 NSMutableArray メッセージは 、 、 、、および のメッセージの組み合わせで、の元の受信者に送信されます。レシーバーのクラスが、パターンまたは (Mac OS 10.4 で導入された) に一致する名前を持つオプションのメソッドも実装している場合-[NSMutableArray insertObjects:atIndexes:]-[NSMutableArray removeObjectsAtIndexes:]-insertObject:in<Key>AtIndex:-removeObjectFrom<Key>AtIndex:-insert<Key>:atIndexes:-remove<Key>AtIndexes:-mutableArrayValueForKey:-replaceObjectIn<Key>AtIndex:withObject:-replace<Key>AtIndexes:with<Key>:その方法は、最適なパフォーマンスが得られる場合に使用されます。
  2. それ以外の場合 (配列ミューテーション メソッドのセットが見つからない場合) は、レシーバーのクラスで、名前が pattern に一致するアクセサー メソッドを検索します-set<Key>:。そのようなメソッドが見つかった場合、コレクション プロキシ オブジェクトに送信される各 NSMutableArray メッセージは -set<Key>:、 の元の受信者に送信されるメッセージになります-mutableArrayValueForKey:
  3. それ以外の場合 (配列ミューテーション メソッドのセットまたは単純なアクセサ メソッドが見つからない場合) で、レシーバのクラスの +accessInstanceVariablesDirectlyメソッドが YES を返した場合、レシーバのクラスを検索して、名前がパターン_<key>or<key>にその順序で一致するインスタンス変数を探します。そのようなインスタンス変数が見つかった場合、コレクション プロキシ オブジェクトに送信された各 NSMutableArray メッセージは、インスタンス変数の値に転送されます。したがって、通常は NSMutableArray のインスタンスまたは NSMutableArray のサブクラスである必要があります。
  4. それ以外の場合 (配列変更メソッドのセット、単純なアクセサー メソッド、またはインスタンス変数が見つからない場合) は、変更可能なコレクション プロキシ オブジェクトを返します。コレクション プロキシ オブジェクトに送信される各 NSMutableArray メッセージは-setValue:forUndefinedKey: 、 の元の受信者に送信されるメッセージになります -mutableArrayValueForKey:。のデフォルトの実装で-setValue:forUndefinedKey:は NSUndefinedKeyException が発生しますが、アプリケーションでオーバーライドできます。
于 2013-06-18T12:21:28.297 に答える