2012-04-07 3 views
7

件数が多い場合は通知を受けたいと思います。 NSArray内の項目の数が変化します。 配列にオブジェクトを追加したり削除したりすることができれば、もちろんこれは必要ありません。しかし、私はそうではありません。ビジネスプロセスモデルに関しては予期せず発生し、外部要因に依存します。 シンプルで洗練されたソリューションがありますか?NSMutableArrayで観測数を調べる

編集:私はもちろんのNSMutableArrayのにこれを修正しています。..

+0

これは100%ではありませんが、配列へのキーパスと接尾辞 '@ count'はこの値を取得するKVCの方法です。だから、おそらくあなたはKVOが 'array @ count'を観察できますか? https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/CollectionOperators.html#//apple_ref/doc/uid/20002176-BAJEAIEE – joerick

答えて

15

あなたはKVCを使用する必要があります。しかし、それをやり遂げる方法は?結局のところ、NSMutableArrayは、その突然変異メソッドや内容の変更に対応するKey-Value-Codingではありません。答えはプロキシです - サブクラス化NS [変更可能]配列はあまりにも面倒です。

NSProxyは、NSMutableArrayのように配列に送信されたメッセージをインターセプトして内部インスタンスに転送するのに使用できる素晴らしいクラスです。残念ながら、それはKVCの勇気がNSObjectに住んでいるので、KVCにも準拠していません。私たちはそれを使わなければなりません。サンプルインターフェースは次のようになります:あなたが見ることができるように、我々はそれがNSMutableArrayであるかのように私たちのプロキシがすべてを実装する必要がありますよう、必要なNSMutableArrayのためのインタフェースを、シミュレートしている

@interface CFIKVCMutableArrayProxy : NSObject { 
    NSMutableArray *_innerArray; 
} 

- (NSUInteger)count; 

- (void)insertObject:(id)anObject atIndex:(NSUInteger)index; 
- (void)removeObjectAtIndex:(NSUInteger)index; 
- (void)addObject:(id)anObject; 
- (void)removeLastObject; 
- (void)insertObjects:(NSArray *)objects atIndexes:(NSIndexSet *)indexes; 
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; 

//… 

@end 

。これにより、セレクタを内部のNSMutableArrayポインタに転送できるので、実装はできるだけシンプルになります。あなたはこのような配列をラップするために何の機会を持っていない場合は、再度考えるあなたのコードにしてみてください

@implementation CFIKVCMutableArrayProxy 

//… 

- (NSUInteger)count { 
    return _innerArray.count; 
} 

- (void)addObject:(id)anObject { 
    [self willChangeValueForKey:@"count"]; 
    [_innerArray addObject:anObject]; 
    [self didChangeValueForKey:@"count"]; 
} 

- (void)removeLastObject { 
    [self willChangeValueForKey:@"count"]; 
    [_innerArray removeLastObject]; 
    [self didChangeValueForKey:@"count"]; 
} 

@end 

:簡潔にするために、私は概要のみがどのようなものかを示すために2つのメソッドを実装します。外部依存がこの種のコーナーにあなたを強制している場合は、それを削除してみてください。自分のツールを回避することは常に悪いことです。 mutableArrayの1の変化を観察する

+0

時間が経過し、幸運な改善があります私のコントロール外のコードの部分に実装することができます。配列を保持するファサードオブジェクトは、モデルが変更されたときにNSNotificationsを発行します。 あなたの提案されたソリューションは注目に値するですが、私がアレイを制御していなかったという重要な事実を見逃してしまいました。だから、配列の代わりにファサードに代理オブジェクトを挿入することはできませんでした。 –

+0

私は何か新しいことを学びました。 – naz

+0

@CodaFi説明をありがとう:) –

6

はKVO準拠である

- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key 

によって与えられた可変プロキシオブジェクトを使用する必要があり、プロキシオブジェクトのすなわち変更が/変更通知をしなかっただろう送ります。

次のデモクラスは

@interface DemoClass : NSObject 

@property (nonatomic) NSMutableArray *items; 

- (void)addItemsObserver:(id)object; 
- (void)removeItemsObserver:(id)object; 

@end 

@implementation DemoClass 

- (NSMutableArray *)items; 
{ 
    return [self mutableArrayValueForKey:@"_items"]; 
} 

- (void)addItemsObserver:(id)object 
{ 
    [self addObserver:object forKeyPath:@"[email protected]" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil]; 
} 

- (void)removeItemsObserver:(id)object 
{ 
    [self removeObserver:object forKeyPath:@"[email protected]" context:nil]; 
} 
@end 


@interface ObservingClass : NSObject 

@property (nonatomic) DemoClass *demoObject; 

@end 

@implementation ObservingClass 

- (instanstype)init 
{ 
    if (self = [super init]) { 
     _demoObject = [DemoClass new]; 

     [_demoObject addItemsObserver:self]; 
    } 
    return self; 
} 

- (void)observeValueForKeyPath:(NSString *)keyPath 
        ofObject:(id)object 
        change:(NSDictionary *)change 
        context:(void *)context 
{ 
    NSLog(@"is called on demoObject.items.count change"); 
} 

- (void)dealloc 
{ 
    [_demoObject removeItemsObserver:self]; 
} 

@end 

完全な実装を示した今、あなたはitemsでオブジェクトを追加または削除するたび、あなたは(observeValueForKeyPathが呼ばれた)コンソールで新しいログが表示されます。

自動合成されたivar _items配列を直接変更しても効果はありません。

また、オブザーバを[email protected]に設定する必要があります([email protected]は無意味です)。

_itemsまたはself.itemsを初期化する必要はありません。あなたがitemsゲッターに電話すると、場面の裏で行われます。

"アレイ"を変更するたびに、itemsの新しいオブジェクト_itemsが新しいアドレスで取得されます。しかし、私はまだitemsプロキシゲッターで見つけることができます。

+0

'removeProxyItemsObserver:'メソッドも必要な場合があります。 –

+0

@AaronBrager、完全性のために追加されました。ありがとう。 – malex