我需要KVO的一些帮助,我差不多在那里。我正在尝试做的是在树控制器中的某些内容发生变化时触发一个方法。
所以我正在使用此代码注册为KVO。
[theObject addObserver: self
forKeyPath: @"myKeyPath"
options: NSKeyValueObservingOptionNew
context: NULL];
但是,当我观察的关键路径发生变化时,如何触发方法?
另外一个问题,当我将自己添加为观察者时,我希望关键路径成为我的核心数据模型中的属性,我是否已正确完成?
答案 0 :(得分:6)
覆盖observeValueForKeyPath:ofObject:change:context:
以分派您要呼叫的方法。
@interface Foo : NSObject {
NSDictionary *dispatch;
...
}
@end
@implementation Foo
-(id)init {
if (self = [super init]) {
dispatch = [[NSDictionary dictionaryWithObjectsAndKeys:NSStringFromSelector(@selector(somethingHappenedTo:with:)),@"myKeyPath",...,nil] retain];
...
}
}
...
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
SEL msg = NSSelectorFromString([dispatch objectForKey:keyPath]);
if (msg) {
[self performSelector:msg withObject:object withObject:keyPath];
}
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
...
有关详细信息,请参阅“Receiving Notification of a Change”。
答案 1 :(得分:5)
我建议您查看Google工具箱For Mac的GTMNSObject+KeyValueObserving.h类别或至少Michael Michael的博客post。基本上,正确地进行手动KVO 非常是微妙的,并且API建议的模式并不理想。在API上放置一个其他层(如GTMNSObject + KeyValueObserving)会更好地使事情更像NSNotification
API并隐藏一些微妙的错误来源。
使用GTMNSObject + KeyValueObserving,你可以
[theObject gtm_addObserver:self
forKeyPath:@"myKeyPath"
selector:@selector(myCallbackSelector:)
userInfo:nil
options:NSKeyValueObservingOptionNew];
,当-myCallbackSelector:
的值因类型为@"myKeyPath"
的参数更改时,您的GTMKeyValueChangeNotification
将被调用,该参数会封装您可能需要的所有相关信息。
这样,您不必在observeValueForKeyPath:ofObject:change:context
中有一个大的调度表(实际上一个是按类别为您维护的),或者必须担心使用{{1}的正确方法}指针,以避免与超级/子类等冲突。
答案 2 :(得分:4)
您应该实现此功能,并在密钥路径更改时调用它:
(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context;
更多信息here。
答案 3 :(得分:3)
(这是我在这里学到的一种技术:http://www.bit-101.com/blog/?p=1999)
您可以在“上下文”中传递该方法,例如
[theObject addObserver:self
forKeyPath:@"myKeyPath"
options:NSKeyValueObservingOptionNew
context:@selector(doSomething)];
..然后在observeValueForKeyPath方法中,将其转换为SEL选择器类型,然后执行它。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
SEL selector = (SEL)context;
[self performSelector:selector];
}
如果要将数据传递给doSomething方法,可以使用“更改”字典中的“新”键,如下所示:
[theObject addObserver:self
forKeyPath:@"myKeyPath"
options:NSKeyValueObservingOptionNew
context:@selector(doSomething:)]; // note the colon
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
SEL selector = (SEL)context;
// send the new value of observed keyPath to the method
[self performSelector:selector withObject:[change valueForKey:@"new"]];
}
-(void)doSomething:(NSString *)newString // assuming it's a string
{
label.text = newString;
}