I added a observer to my collection, and observe the count on it
[[[JHTaskSave defaults] tasks] addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
JHTaskSave is a singleton object and tasks is a JHTaskCollection KVC compliant, when I add an object to my collection:
[[[JHTaskSave defaults] tasks] addTask:newTask]
The count of tasks changes but the observeValueForKeyPath is not called, I don't understand why
Here is my collection class:
@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
Based on the code you posted, if you want count
to be Key-Value Observable, you need to send willChangeValueForKey
and didChangeValueForKey
notifications any time you mutate the collection in a way that changes the count. Using your code:
@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