gpt4 book ai didi

ios - 由 NSMutableArray 支持的 NSArray 修改的 KVO 通知

转载 作者:技术小花猫 更新时间:2023-10-29 11:14:10 24 4
gpt4 key购买 nike

我正在尝试使用 KVO 来监听 NSArray 属性上的集合更改事件。公开地,该属性是一个只读的 NSArray,但由 NSMutableArray ivar 支持,因此我可以修改集合。

我知道我可以将属性设置为新值以获得“设置”更改,但我对添加、删除、替换更改感兴趣。我如何正确通知 NSArray 的这些类型的更改?

@interface Model : NSObject

@property (nonatomic, readonly) NSArray *items;

@end

@implementation Model {
NSMutableArray *_items;
}

- (NSArray *)items {
return [_items copy];
}

- (void)addItem:(Item *)item {
[_items addObject:item];
}

@end

Model *model = [[Model alloc] init];

[observer addObserver:model
forKeyPath:@"items"
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
context:NULL];

Item *item = [[Item alloc] init];
[model addItem:newItem];

观察者类:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"items"]) {
//Not called
}
}

最佳答案

首先,您应该了解 KVO 用于观察对象其属性的变化。也就是说,您不能像这样“观察数组”,而是观察索引集合属性。该属性可能由数组支持或以其他方式实现。只要符合KVC,按照KVO兼容的方式修改就可以了。 (因此,属性是 NSArray* 类型还是使用 NSMutableArray* 或其他任何类型实现都没有关系。)

因此,您正在观察 Model 的实例,以了解其 items 属性的变化。如果您希望观察者获得更改通知,您必须确保始终以符合 KVO 的方式修改 items 属性。

在我看来,最好的方法是实现 mutable indexed collection accessors并始终使用它们来修改属性。因此,您至少要实现其中一项:

- (void) insertObject:(id)anObject inItemsAtIndex:(NSUInteger)index;
- (void) insertItems:(NSArray *)objects atIndexes:(NSIndexSet *)indexes;

其中之一:

- (void) removeObjectFromItemsAtIndex:(NSUInteger)index;
- (void) removeItemsAtIndexes:(NSIndexSet *)indexes;

当属性由 NSMutableArray 支持时,上述方法是对 _items 上相应方法的直接包装。

您为修改属性而编写的任何其他方法都应该通过其中之一。因此,您的 -addItem: 方法将是:

- (void)addItem:(Item *)item {
[self insertObject:item inItemsAtIndex:[_items count]];
}

您还可以删除 items 属性的普通 getter,而只公开索引集合的 getter:

- (NSUInteger) countOfItems;
- (id) objectInItemsAtIndex:(NSUInteger)index;

不过,如果有典型的 getter,则没有必要。

(这些访问器的存在允许你实现一个非 NSArray 类型的对多属性。从 KVC 的角度来看,没有必要为任何实际的数组类型界面。)

就我个人而言,我不推荐这样做,但是一旦你有了这样的访问器,你也可以通过使用 -mutableArrayValueForKey 获取属性的类似 NSMutableArray 的代理来改变属性: 然后向它​​发送变异操作。因此,在这种情况下,您可以执行 [[self mutableArrayValueForKey:@"items"] addObject:item]。我不喜欢这样,因为我觉得键值编码是针对当键是数据的时候。它是动态的或存储在像 NIB 这样的数据文件中,在编译时是未知的。当您可以选择使用语言符号(例如选择器)来寻址属性时,对键名称进行硬编码是一种代码味道。

不过,就索引访问器而言,对于真正难以实现的操作(例如排序)来说,这是有道理的。

最后,您可以使用 NSKeyValueObserving协议(protocol)的 -willChange...-didChange... 方法在您直接修改属性的后备存储时发出更改通知,而无需通过 KVO 可以识别和识别的突变方法钩入。对于索引集合属性,这将是 -willChange:valuesAtIndexes:forKey:-didChange:valuesAtIndexes:forKey: 方法。就我而言,这是一种更糟糕的代码味道。

关于ios - 由 NSMutableArray 支持的 NSArray 修改的 KVO 通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24088953/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com