Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
609 views
in Technique[技术] by (71.8m points)

objective c - Receiving 2 KVO notifications for a single KVC change

I'm using KVC/KVO to create a custom bindings implementation for a University project (it needs to be custom as I want to do things beyond what bindings can do, including running on iOS).

I have a 'bindings controller' that registers for KVO notifications on a number of keys on an object (using addObserver:forKeyPath:options:context:) and I do receive notifications. However I am receiving two notifications for each change. I have an idea for a workaround, but I would rather work out why this is happening and correct it!

Does anyone have any ideas why this might be happening? I'm certain I have only registered each notification a single time, and deregistering a single time causes both of the notifications to stop.

Thanks.

Edit:

I have a request for some code, so I'll put some in. It's a bit rough at the moment, it's essentially still a proof of concept, so bear with me.

This is one of the properties I am observing (I know it's a bit strange, but this class essentially exposes certain properties of an NSManagedObject as properties of itself):

- (void)setName:(NSString *)name
{
    [self willChangeValueForKey:@"name"];
    [contact setFirstName:name];
    [self didChangeValueForKey:@"name"];
}

This is the code I use to observe that property (confirmed to only run once, and only in a single place):

[viewModel addObserver:self
            forKeyPath:@"name"
               options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial)
               context:viewController];

Any calls after that which change that property, e.g.:

viewModel.name = @"Joe";
[viewModel setName: @"Joe"];
[viewModel setValue: @"Joe" forKey: @"name"];

will cause the method:

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

to be called twice, with the same arguments each time.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You're doing this:

- (void)setName:(NSString *)name
{
    [self willChangeValueForKey:@"name"];
    [contact setFirstName:name];
    [self didChangeValueForKey:@"name"];
}

But (by the sounds of it) from a non-NSManagedObject subclass. This means that Cocoa will be attempting to send KVO notifications automatically for you. You're supplementing that by sending your own too. Solutions:

  • Override +automaticallyNotifiesObserversForKey: to return NO
  • Change your method to:

    - (void)setName:(NSString *)name { [contact setFirstName:name]; }


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...