views:

96

answers:

3

I'm developing simple MVC app in Cocoa/Objective-C. I have a strange issue (or misunderstanding) with notifications and KVO.

I have AppController object in MainMenu.xib, hence I implement awakeFromNib method where I register for NSImageView changing its image property. I add self as an observer in the following way:

// options:3 equals to new/old passed values in changeDictionary
[backgroundImageView addObserver:self 
                      forKeyPath:@"image" 
                         options:3
                         context:NULL];

The backgroundImageView is an IBOutlet in AppController connected to NSImageView.

In standard observeValueForKeyPath:ofObject:change:context method I just log the received notification.

Problem is - when i change the image value of NSImageView I get 3 notifications instead of one. Can you help me with this? Maybe I'm overlooking something in options or in generally registering observer?

UPDATE: backgroundImageView is the instance of BackgroundImageView class which is sublcass of NSImageView. I subclassed the latter one for handling drag and drop operations as drag destination. When performDragOperation: is called (the last 'state' of the dragging) it changes the value for image property with setImage between willChangeValueForKey and didChangeValueForKey.

+1  A: 

Is your AppController the File's Owner of two other nibs? If so, it'll receive an awakeFromNib message for each of those, too. MainMenu plus two makes three awakeFromNib messages, which means you'll add yourself as an observer three times.

Peter Hosey
AppController is an object in MainMenu.xib. It's not a file owner.
Eimantas
A: 

There does not seem to be any obvious problem with setting of the observer.

Have a look at how you update the image that you observe, maybe it's being modified 3 times?

stefanB
I updated the question with needed details.
Eimantas
Eimantas: Are you sure you saved your changes? It's not showing me an edit.
Peter Hosey
Refresh! I wrote the comment before writing the updates ,)
Eimantas
+1  A: 

… it changes the value for image property with setImage between willChangeValueForKey and didChangeValueForKey.

When you send an accessor message, you get KVO notifications for free with it. You should remove the {will,did}ChangeValueForKey: messages, because they're the cause of at least one of the extraneous change notifications.

Peter Hosey
I'm not sure why would any of `{will,did}ChangeValueForKey:` cause KVO notification, I assume those methods alone don't modify `image` property of the view, they only provide ways for extended class to disable change or do some extra work when value changed, do you have any specific reason or example?
stefanB
Posting KVO notifications (without an accessor) is the very purpose of `{will,did}ChangeValueForKey`. When you do have an accessor, and you use it, KVO sends those messages for you.
Peter Hosey
See the relevant section of the KVO Programming Guide: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/KeyValueObserving/Concepts/AutoVsManual.html
Peter Hosey
Wow, thanks! I will try it out!
Eimantas