我在我的收藏中添加了一个观察者,并观察它的计数
[[[JHTaskSave defaults] tasks] addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
当我将一个对象添加到我的集合中时,JHTaskSave是一个单例对象,并且任务是符合JHTaskCollection KVC的:
[[[JHTaskSave defaults] tasks] addTask:newTask]
任务计数发生变化但是没有调用observeValueForKeyPath,我不明白为什么
这是我的收藏类:
@interface JHTaskCollection : NSObject <NSFastEnumeration>
{
NSMutableArray *_tasks;
}
@property (nonatomic) NSUInteger count;
- (id)taskAtIndex:(NSUInteger)index;
- (void)addTask:(JHTask *)task;
- (void)removeTask:(JHTask *)task;
- (void)insertObject:(id)key inTasksAtIndex:(NSUInteger)index;
- (void)removeObjectFromTasksAtIndex:(NSUInteger)index;
- (void)removeTaskAtIndexes:(NSIndexSet *)indexes;
- (NSArray *)taskAtIndexes:(NSIndexSet *)indexes;
@end
@implementation JHTaskCollection
- (id)init
{
if(self = [super init]) {
_tasks = [[NSMutableArray alloc] init];
}
return self;
}
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained *)stackbuf count:(NSUInteger)len
{
return [_tasks countByEnumeratingWithState:state objects:stackbuf count:len];
}
- (NSArray *)taskAtIndexes:(NSIndexSet *)indexes
{
return [_tasks objectsAtIndexes:indexes];
}
- (void)insertObject:(id)key inTasksAtIndex:(NSUInteger)index
{
[_tasks insertObject:key atIndex:index];
}
- (void)removeObjectFromTasksAtIndex:(NSUInteger)index
{
[_tasks removeObjectAtIndex:index];
}
- (void)removeTaskAtIndexes:(NSIndexSet *)indexes
{
[_tasks removeObjectsAtIndexes:indexes];
}
- (JHTask *)taskAtIndex:(NSUInteger)index
{
return [_tasks objectAtIndex:index];
}
- (NSUInteger)count
{
return _tasks.count;
}
- (void)addTask:(JHTask *)task
{
[_tasks addObject:task];
}
- (void)removeTask:(JHTask *)task
{
[_tasks removeObject:task];
}
@end
答案 0 :(得分:1)
根据您发布的代码,如果您希望count
成为Key-Value Observable,则需要在以某种方式改变集合时发送willChangeValueForKey
和didChangeValueForKey
通知这改变了计数。使用您的代码:
@implementation JHTaskCollection
- (id)init
{
if(self = [super init]) {
_tasks = [[NSMutableArray alloc] init];
}
return self;
}
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained *)stackbuf count:(NSUInteger)len
{
return [_tasks countByEnumeratingWithState:state objects:stackbuf count:len];
}
- (NSArray *)taskAtIndexes:(NSIndexSet *)indexes
{
return [_tasks objectsAtIndexes:indexes];
}
- (void)insertObject:(id)key inTasksAtIndex:(NSUInteger)index
{
[self willChangeValueForKey: @"count"];
[_tasks insertObject:key atIndex:index];
[self didChangeValueForKey: @"count"];
}
- (void)removeObjectFromTasksAtIndex:(NSUInteger)index
{
[self willChangeValueForKey: @"count"];
[_tasks removeObjectAtIndex:index];
[self didChangeValueForKey: @"count"];
}
- (void)removeTaskAtIndexes:(NSIndexSet *)indexes
{
[self willChangeValueForKey: @"count"];
[_tasks removeObjectsAtIndexes:indexes];
[self didChangeValueForKey: @"count"];
}
- (JHTask *)taskAtIndex:(NSUInteger)index
{
return [_tasks objectAtIndex:index];
}
- (NSUInteger)count
{
return _tasks.count;
}
- (void)addTask:(JHTask *)task
{
[self willChangeValueForKey: @"count"];
[_tasks addObject:task];
[self didChangeValueForKey: @"count"];
}
- (void)removeTask:(JHTask *)task
{
[self willChangeValueForKey: @"count"];
[_tasks removeObject:task];
[self didChangeValueForKey: @"count"];
}
@end
答案 1 :(得分:0)
有两个原因导致count
的通知未触发,这两者都与键值编码有关。
第一个原因是因为调用count
时addTask:
属性未更新。 count
属性与_tasks数组的计数之间没有直接链接。操作数组的任何代码都必须包含在-willChangeValueForKey:
和-didChangeValueForKey:
调用之间。但是,KVO协议提供了设置从属密钥的能力。由于count属性受数组影响,因此可以使用
+ (NSSet*) keyPathsForValuesAffectingCount {
return [NSSet setWithObject:@"tasks"];
}
或更通用的+ keyPathsForValuesAffectingValueForKey:(NSString *)key
。实施任一项都会在count
被修改时触发tasks
的通知。
这不起作用的第二个原因是因为您没有按照Key-Value Coding Programming Guide中定义的符合键值的方式更新tasks
数组。基本上,有序集合中的对象必须添加
-insertObject:in<Key>AtIndex:
-insert<Key>:atIndexes:
或者使用will|didChangeValueForKey:
来电。
在您的示例中,如果在设置密钥依赖项后提供以下实现,则应观察更改。
- (void)addTask:(JHTask *)task
{
[self insertObject:task inTasksAtIndex:[_tasks count]];
}
答案 2 :(得分:-2)