2013-06-03 79 views
1

我添加了一個觀測到我的收藏,並觀察指望它KVO對集合

[[[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

從JHTaskCollection誰是一個定製的NSMutableArray – james075

+0

不JHTaskCollection子類NSMutableArray的或沒有每個實例有一個NSMutableArray? –

+0

集合對象上的KVO工作方式不同。按照此方法[收集KVO](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/AccessorConventions.html#//apple_ref/doc/uid/20002174-178830 -BAJEDEFB) – Amar

回答

1

根據您發佈,如果你想count是鍵值可觀察的代碼,你需要發送willChangeValueForKeydidChangeValueForKey通知您變異集合中改變計數的方式任意時間。使用代碼:

@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 
+0

另一種方法是使用可以簡化代碼的屬性。 'self.count = _tasks.count;'這會產生將/改變消息。 – Tricertops

-2

-(NSInteger) count是一種方法,正因爲如此,你不能使用志願監視它 - 你可以使用AOP但我認爲這是不是你想去的方向。

也許相反,你可以直接監視集合,而不是計數,儘管我不確定你是否可以用KVO來做到這一點(我認爲你可以) - 你需要添加一個addObject:方法,並在那裏做你的魔法?

編輯:

你可以使用「的方法混寫」,如this blog擺出來,但是否值得加入默默無聞?

+0

KVO在keyPaths中進行交易。它並不關心某物是一種方法還是一種財產,或者一種伊娃,或者其他任何東西。如果OP希望可以觀察,他們必須使其可觀察。但沒有任何關於它是一種方法意味着你不能使用KVO來監控它。 AOP不是答案,也不是方法混合。 – ipmcc

0

有幾個原因爲什麼count的通知沒有觸發,都與鍵值編碼有關。

第一個原因是因爲調用addTask:count屬性未更新。 count屬性和_tasks數組的計數之間沒有直接關聯。操縱數組的任何代碼都必須在-willChangeValueForKey:-didChangeValueForKey:調用之間打包。但是,KVO協議提供了設置相關密鑰的功能。由於計數屬性由陣列的影響,可以通過使用

+ (NSSet*) keyPathsForValuesAffectingCount { 
    return [NSSet setWithObject:@"tasks"]; 
} 

或者更一般的+ keyPathsForValuesAffectingValueForKey:(NSString *)key設置這兩個鍵之間的依賴關係。當tasks被修改時,實現兩者都將觸發count的通知。

第二個原因不起作用,是因爲您沒有按照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]]; 
} 
+0

影響計數的理想keypath是'「tasks.count」',但是** 1。**他沒有'tasks'屬性,只是簡單的ivar和** 2。**數組的數量不可觀察。但總的來說,您的答案是指定KVO依賴性的最佳方法。 – Tricertops