我正在尝试观察用ObjectiveC编写的对象中NSMutableArray
的值更改。然而,观察者是用Swift编写的UIViewController
。
我无法获得KVO通知。这些是我的改变:
@interface Record : BaseObject
@property (nonatomic) NSMutableArray *commentsArray;
-(NSUInteger) countOfCommentsArray {
return _commentsArray.count;
}
-(id) objectInCommentsArrayAtIndex:(NSUInteger)index {
return [_commentsArray objectAtIndex:index];
}
-(void) insertObject:(Comment *)comment inCommentsAtIndex:(NSUInteger)index {
[_commentsArray insertObject:comment atIndex:index];
}
-(void) insertComments:(NSArray *)array atIndexes:(NSIndexSet*)indexes {
[_commentsArray insertObjects:array atIndexes:indexes];
}
-(void) removeCommentsAtIndexes:(NSIndexSet *)indexes {
[_commentsArray removeObjectsAtIndexes:indexes];
}
-(void) removeObjectFromCommentsAtIndex:(NSUInteger)index {
[_commentsArray removeObjectAtIndex:index];
}
-(void) replaceObjectInCommentsAtIndex:(NSUInteger)index withObject:(id)object {
[_commentsArray replaceObjectAtIndex:index withObject:object];
}
BaseObject派生自NSObject
。
在我的Observer类中,它是一个Viewcontroller,用Swift编写,我有以下内容。
在其中一种设置方法中。
myInspectionRecord?.addObserver(self, forKeyPath: "commentsArray", options: NSKeyValueObservingOptions.New, context: nil);
我有方法覆盖。
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
print("Value Changed");
}
但不知何故,当我使用API本身向数组添加新对象时,似乎不会触发observeValue
方法。
关于我在这里可能缺少什么的任何指示?
或者KVO在Swift和Objective C文件之间不起作用吗?
任何帮助将不胜感激。 谢谢!
答案 0 :(得分:0)
您已根据Apple's KVC guide实施了多对键值编码(!)方法,但方法名称错误。
由于您的属性名为commentsArray
,因此所有方法都需要包含该全名。例如,您的insertObject:inCommentsAtIndex:
应命名为insertObject:inCommentsArrayAtIndex:
。
根据this answer,这应该免费给你KVO调用,但你必须实际调用它们:编译器似乎认识到它需要为这些方法注入所需的KVO调用。
现在你的代码问题是,你的方法都没有改变属性,即使编译器注入了KVO代码,它也会针对错误的密钥路径执行此操作({{1}而不是comments
)。有两个解决方案:似乎使用那些KVC方法免费给你KVO,但我从来没有使用过这种魔法,所以我不知道它是否会起作用。不过应该这样。
如果您想以完全不同的方式修改数组,可以使用“强力”方式:自己调用KVO methods willChangeValueForKey:
and didChangeValueForKey:
甚至更好,willChange:valuesAtIndexes:forKey:
and didChange:valuesAtIndexes:forKey:
,如下所示:
commentsArray
(我喜欢使用[self willChangeValueForKey:NSStringFromSelector(@selector(commentsArray))];
// Modify commentsArray
[self didChangeValueForKey:NSStringFromSelector(@selector(commentsArray))];
// or better, for an insertion:
NSIndexSet *set = [NSIndexSet indexSetWithIndex:someIndex];
NSString *key = NSStringFromSelector(@selector(commentsArray));
[self willChange:NSKeyValueChangeInsertion valuesAtIndexes:set forKey:key];
[_commentsArray insertObject:someObject atIndex:someIndex];
[self didChange:NSKeyValueChangeInsertion valuesAtIndexes:set forKey:key];
而不是NSStringFromSelector(@selector(commentsArray))
,因为编译器会知道它是一个选择器,然后重构会在重命名属性时发出警告。)