Ear*_*rey 7 objective-c nsarray ios
我希望在计数时得到通知,即.NSArray中的项目数量发生了变化..当然我不需要这个,如果我控制添加和删除数组中的对象.但我不是,它在业务流程模型方面无法预测,并且取决于外部因素.有一些简单优雅的解决方案吗?
编辑:我当然正在纠正这个NSMutableArray ..
Cod*_*aFi 15
你需要使用KVC.但是如何去做呢?毕竟,NSMutableArray不符合其变异方法或内容更改的键值编码.答案是代理-as子类NS [Mutable]数组太麻烦了.
NSProxy是一个很棒的小类,您可以使用它来拦截发送到您的数组的消息,就像您是NSMutableArray一样,然后将它们转发到某个内部实例.不幸的是,它也不符合KVC,因为KVC的胆量存在于NSObject中.那么我们必须使用它.示例界面可能如下所示:
@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
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我们正在模拟一个接口NSMutableArray,这是必要的,因为我们的代理应该实现所有内容,就好像它是一样NSMutableArray.这也使得实现尽可能简单,因为我们可以将选择器转发到我们的内部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
Run Code Online (Sandbox Code Playgroud)
如果您没有机会像这样包装数组,那么请尝试重新考虑您的代码.如果外部依赖项迫使您进入此类角落,请尝试将其删除.解决自己的工具总是一件坏事.
要观察mutableArray中的更改,需要使用由给定的可变代理对象
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key
Run Code Online (Sandbox Code Playgroud)
符合KVO,即代理对象的任何更改都会发送/更改通知.
以下演示类显示了完整的实现
@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:@"_items.@count" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
}
- (void)removeItemsObserver:(id)object
{
[self removeObserver:object forKeyPath:@"_items.@count" 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
Run Code Online (Sandbox Code Playgroud)
现在,每次添加或删除对象时,items您都会看到新的登录控制台(observeValueForKeyPath被称为).
任何直接改变自动合成的ivar _items阵列都没有效果.
另请注意,您需要设置观察者_items.@count(观察items.@count是无意义的).
请注意,您不需要初始化_items或self.items.当你打电话给itemsgetter 时,它将在幕后完成.
每次更改"数组"时,items您都将获得_items具有新地址的新对象.但我仍然可以通过items代理getter 找到它.
| 归档时间: |
|
| 查看次数: |
8119 次 |
| 最近记录: |