帮助观察键值

发布于 2024-08-06 16:53:02 字数 354 浏览 8 评论 0 原文

我需要一些关于 KVO 的帮助,我已经完成一半了。我想做的是当树控制器中的某些内容发生变化时触发一个方法。

所以我使用此代码注册为 KVO。

[theObject addObserver: self
            forKeyPath: @"myKeyPath"
               options: NSKeyValueObservingOptionNew
               context: NULL];

但是当我观察到的关键路径发生变化时如何触发方法?

还有一个问题,当我将自己添加为观察者时,我希望关键路径成为我的核心数据模型中的一个属性,我做得正确吗?

I need a bit of help with KVO, I'm about half way there. What I'm trying to do is trigger a method when something in an Tree Controller changes.

So I 'm using this code to register as a KVO.

[theObject addObserver: self
            forKeyPath: @"myKeyPath"
               options: NSKeyValueObservingOptionNew
               context: NULL];

But how do i trigger a method when the Key Path I am observing changes?

One extra question, when I add my self as an Observer I want the Key Path to be a Property in my Core Data model, Have I done that correctly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

段念尘 2024-08-13 16:53:02

重写 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];
}
...

请参阅“接收更改通知”了解详细信息。

Override observeValueForKeyPath:ofObject:change:context: to dispatch the method you wish to call.

@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];
}
...

See "Receiving Notification of a Change" for details.

青衫负雪 2024-08-13 16:53:02

我建议您查看 Google Toolbox For Mac 的 GTMNSObject+KeyValueObserving.h 类别或至少是博客 Michael Ash 的帖子 激发了它的灵感。基本上,正确执行手动 KVO 非常微妙,并且 API 建议的模式并不理想。最好在 API 上放置一个其他层(如 GTMNSObject+KeyValueObserving),这使得事情更像 NSNotification API 并隐藏一些细微错误的来源。

使用 GTMNSObject+KeyValueObserving,

[theObject gtm_addObserver:self
                forKeyPath:@"myKeyPath"
                  selector:@selector(myCallbackSelector:)
                  userInfo:nil
                   options:NSKeyValueObservingOptionNew];

@"myKeyPath" 处的值随着 GTMKeyValueChangeNotification 类型的参数发生变化时,您的 -myCallbackSelector: 将被调用code>,它封装了您可能需要的所有相关信息。

这样,您就不必在 observeValueForKeyPath:ofObject:change:context 中有一个大的调度表(实际上是由类别为您维护的),也不必担心正确的方法使用context指针来避免与父类/子类等发生冲突。

I would recommend you take a look at the Google Toolbox For Mac's GTMNSObject+KeyValueObserving.h category or at least the blog post by Michael Ash that inspired it. Basically, doing manual KVO right is very subtle and the pattern suggested by the API is not ideal. It's much better to put an other layer on the API (as GTMNSObject+KeyValueObserving) does that makes things more like the NSNotification API and hides some of the sources of subtle bugs.

Using GTMNSObject+KeyValueObserving, you would do

[theObject gtm_addObserver:self
                forKeyPath:@"myKeyPath"
                  selector:@selector(myCallbackSelector:)
                  userInfo:nil
                   options:NSKeyValueObservingOptionNew];

and your -myCallbackSelector: will get called when the value at @"myKeyPath" changes with an argument of type GTMKeyValueChangeNotification, which encapsulates all the relevant information you might need.

This way, you don't have to have a big dispatch table in observeValueForKeyPath:ofObject:change:context (in reality one is maintained for you by the category) or have to worry about the correct way to use the context pointer to avoid conflict with super/sub classes etc.

孤独难免 2024-08-13 16:53:02

您应该实现此功能,并且当键路径更改时它将被调用:

 (void)observeValueForKeyPath:(NSString *)keyPath
                     ofObject:(id)object
                       change:(NSDictionary *)change
                      context:(void *)context;

更多信息 这里

You should implement this and it will be invoked when the keypath changes:

 (void)observeValueForKeyPath:(NSString *)keyPath
                     ofObject:(id)object
                       change:(NSDictionary *)change
                      context:(void *)context;

More info here.

逆蝶 2024-08-13 16:53:02

(这是我在这里学到的一项技术: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 方法,您可以使用“change”字典中的“new”键,如下所示:

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

( this is a technique I learned here: http://www.bit-101.com/blog/?p=1999 )

You could pass the method in the 'context', like

[theObject addObserver:self 
            forKeyPath:@"myKeyPath"
               options:NSKeyValueObservingOptionNew
               context:@selector(doSomething)];

..then in the observeValueForKeyPath method, you cast it to the SEL selector type, and then perform it.

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    SEL selector = (SEL)context;
    [self performSelector:selector];
}

If you want to pass data to the doSomething method you could use the 'new' key in the 'change' dictionary, like this:

[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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文