8

NSMutableArray で key-value-observing を機能させようとしています。以下は、監視対象クラスである MyObservee の .h ファイルです。

@interface MyObservee : NSObject {
    @private int someValue;
    @private NSMutableArray *someArray;
}

@property (readwrite,assign) int someValue;
- (NSMutableArray *)someArray;
@end

クラス MyObserver は、observeValueForKeyPath:ofObject:change:context: を実装します。オブザーバーを追加する方法は次のとおりです。

MyObservee *moe = [[MyObservee alloc] init];
MyObserver *mobs = [[MyObserver alloc] init];

[moe addObserver:mobs 
      forKeyPath:@"someArray" 
         options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) 
         context:NULL];

[moe.someArray addObject:@"hi there"];

addObject: メッセージが someArray キー パスの変更としてトリガーされないのはなぜですか? ここで私が完全に理解していない何かがあると感じています。

4

3 に答える 3

13

KVC プログラミング ガイドで定義されているように、インデックス付き配列アクセサーを実装する必要があります。次に、これらのアクセサーを使用して配列にアクセスする必要があり、KVO トリガーが機能します。-mutableArrayValueForKey:を呼び出し、その配列を addObject: などに使用することもできます。これにより、アクセサー メソッドが呼び出され、KVO トリガーも同様に発生します。NSSets で使用するための set アクセサーもあります。こちらこちらを参照してください。

例:

@interface MyClass : NSObject
{
    NSMutableArray *_orders;
}

@property(retain) NSMutableArray *orders;

- (NSUInteger)countOfOrders;
- (id)objectInOrdersAtIndex:(NSUInteger)index;
- (void)insertObject:(id)obj inOrdersAtIndex:(NSUInteger)index;
- (void)removeObjectFromOrdersAtIndex:(NSUInteger)index;
- (void)replaceObjectInOrdersAtIndex:(NSUInteger)index withObject:(id)obj;


@end
于 2009-01-25T06:43:55.073 に答える
4

残念ながら、NSArray クラスは KVO に準拠していません。それらは KVC に準拠していますが、ここで行おうとしているように直接観察することはできません。この機能を取得する最も簡単な方法は、NSArrayController を使用することです。NSArray コントローラは KVO に準拠しており、アイテムが追加または削除されると警告します。あなたの例では、配列自体を実際に変更すると、オブザーバーに通知されます。たとえば、次のようなことをしたとします。

[moe setSomeArray:[NSMutableArray array]];

これはおそらくあなたが望んでいたものではありません:) 余談ですが、NSDictionaryは実際にはKVOに準拠しているため、選択した場合はそれを使用できます. または、バッキング ストアとして実際の可変配列を作成するだけで、それ以外のすべてのメッセージを転送する NSMutableArray のラッパー サブクラスを作成するaddObjectことremoveObjectもできます。これをオーバーライドして通知をトリガーすることもできます。

于 2009-01-25T06:17:16.920 に答える
3

プライベート配列を別のオブジェクトに渡すのはなぜですか? 他のオブジェクトに処理させると、それほどプライベートではなくなります。

s-bug が言ったように、アクセサーを実装しmutableArrayValueForKey:、プロパティを変更するために使用する必要があります。そのプライベート配列をまったく公開してはならないことを付け加えておきますsomeArray。メソッドは、配列の不変のコピーを返す必要があります。

さらに、s-bug の回答に対する Jason Coco のコメントに注目してください。彼の言い方を言い換えると、おそらくとNSArrayControllerを分離する追加のステップとして を使用する必要がmyObserveeありmyObserverます。これは非常に良い提案であり、プロパティを直接観察する特別な理由がない場合は、それを取る必要があります。(利点の 1 つは、バインディングを使用してビューを新しい配列コントローラーに接続できることです。)

于 2009-01-25T10:22:18.517 に答える