件数が多い場合は通知を受けたいと思います。 NSArray内の項目の数が変化します。 配列にオブジェクトを追加したり削除したりすることができれば、もちろんこれは必要ありません。しかし、私はそうではありません。ビジネスプロセスモデルに関しては予期せず発生し、外部要因に依存します。 シンプルで洗練されたソリューションがありますか?NSMutableArrayで観測数を調べる
編集:私はもちろんのNSMutableArrayのにこれを修正しています。..
件数が多い場合は通知を受けたいと思います。 NSArray内の項目の数が変化します。 配列にオブジェクトを追加したり削除したりすることができれば、もちろんこれは必要ありません。しかし、私はそうではありません。ビジネスプロセスモデルに関しては予期せず発生し、外部要因に依存します。 シンプルで洗練されたソリューションがありますか?NSMutableArrayで観測数を調べる
編集:私はもちろんのNSMutableArrayのにこれを修正しています。..
あなたは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の変化を観察する
時間が経過し、幸運な改善があります私のコントロール外のコードの部分に実装することができます。配列を保持するファサードオブジェクトは、モデルが変更されたときにNSNotificationsを発行します。 あなたの提案されたソリューションは注目に値するですが、私がアレイを制御していなかったという重要な事実を見逃してしまいました。だから、配列の代わりにファサードに代理オブジェクトを挿入することはできませんでした。 –
私は何か新しいことを学びました。 – naz
@CodaFi説明をありがとう:) –
は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
プロキシゲッターで見つけることができます。
'removeProxyItemsObserver:'メソッドも必要な場合があります。 –
@AaronBrager、完全性のために追加されました。ありがとう。 – malex
これは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