用 Swift 编写的 UIViewController 可以充当用 ObjC 编写的对象的观察者吗
Can a UIViewController written in Swift act as an Observer for an Object written in ObjC
我正在尝试观察用 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
。
在我的观察者 class 中,它是一个 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 文件之间工作?
如有任何帮助,我们将不胜感激。
谢谢!
您已经根据 Apple's KVC guide 实现了 to-many key-value coding (!) 方法,但是方法名称是错误的。
由于您的 属性 被命名为 commentsArray
,所有方法都需要包含该全名。例如,您的 insertObject:inCommentsAtIndex:
应命名为 insertObject:inCommentsArrayAtIndex:
.
根据 this answer 这应该会免费为您提供 KVO 调用,但您必须实际调用它们:编译器似乎认识到它需要为这些方法注入所需的 KVO 调用。
你的代码现在的问题是,你的方法都没有改变属性,即使编译器确实注入了 KVO 代码,它也会这样做错误的密钥路径(comments
而不是 commentsArray
)。有两种解决方案:似乎使用那些 KVC-methods 可以免费为您提供 KVO,但我从未使用过这种魔法,所以根据经验我不知道它是否有效。不过应该可以。
如果您想以完全不同的方法修改数组,可以使用 "brute-force" 方法:自己调用 KVO methods willChangeValueForKey:
and didChangeValueForKey:
or even better, willChange:valuesAtIndexes:forKey:
and didChange:valuesAtIndexes:forKey:
,如下所示:
[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))
而不是 @"commentsArray"
,因为编译器随后知道它是一个选择器,并且重构会在您重命名 属性 时警告您。)
我正在尝试观察用 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
。
在我的观察者 class 中,它是一个 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 文件之间工作?
如有任何帮助,我们将不胜感激。 谢谢!
您已经根据 Apple's KVC guide 实现了 to-many key-value coding (!) 方法,但是方法名称是错误的。
由于您的 属性 被命名为 commentsArray
,所有方法都需要包含该全名。例如,您的 insertObject:inCommentsAtIndex:
应命名为 insertObject:inCommentsArrayAtIndex:
.
根据 this answer 这应该会免费为您提供 KVO 调用,但您必须实际调用它们:编译器似乎认识到它需要为这些方法注入所需的 KVO 调用。
你的代码现在的问题是,你的方法都没有改变属性,即使编译器确实注入了 KVO 代码,它也会这样做错误的密钥路径(comments
而不是 commentsArray
)。有两种解决方案:似乎使用那些 KVC-methods 可以免费为您提供 KVO,但我从未使用过这种魔法,所以根据经验我不知道它是否有效。不过应该可以。
如果您想以完全不同的方法修改数组,可以使用 "brute-force" 方法:自己调用 KVO methods willChangeValueForKey:
and didChangeValueForKey:
or even better, willChange:valuesAtIndexes:forKey:
and didChange:valuesAtIndexes:forKey:
,如下所示:
[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))
而不是 @"commentsArray"
,因为编译器随后知道它是一个选择器,并且重构会在您重命名 属性 时警告您。)