3

Possible Duplicate:
Receiving 2 KVO notifications for a single KVC change

I'm confused about where I should be using willChangeValueForKey: and didChangeValueForKey:.

I have an object with a property which requires a custom setter method. As per the Apple documentation, I am using will/didChangeValueForKey::

To implement manual observer notification, you invoke willChangeValueForKey: before changing the value, and didChangeValueForKey: after changing the value. The example in Listing 3 implements manual notifications for the openingBalance property.

Listing 3 Example accessor method implementing manual notification

- (void)setOpeningBalance:(double)theBalance {
    [self willChangeValueForKey:@"openingBalance"];
    _openingBalance = theBalance;
    [self didChangeValueForKey:@"openingBalance"];
}

This makes my object look something like the below:

@interface cObject
@property (readwrite, nonatomic) BOOL Property;
@end

@implementation cObject
- (void)setProperty:(BOOL)Property
{
   [self willChangeValueForKey:@"Property"];
   _Property = Property;
   [self didChangeValueForKey:@"Property"];
   //Do some other stuff
}
@end

The source of my confusion is that if I set up another object to observe Property on an instance of cObject and then call [myObject setProperty:], my observer's callback function is hit twice. Looking at the stack: the first hit happens as a result of me calling didChangeValueForKey:, the second hit is a direct result of me calling setProperty: (i.e. my custom setter does not appear in the stack).

To further add to the confusion, if I change _Property in another function elsewhere in cObject, my observer will not be notified (unless I use did/willChangeValueForKey:, of course!).

EDIT: Even if I do not change _Property in my custom setter, KVO notifies my observer that it has changed. From this, I conclude that KVO is being invoked as just a result of me calling the setter, regardless of whether anything changes or not...

Can anybody explain how my situation differs from that explained in the documentation?

Community
  • 1
  • 1
sam-w
  • 7,478
  • 1
  • 47
  • 77
  • 1
    are you sure it's hit twice for the same object? perhaps multiple observers of a single object? or a single observer registered twice? – Fernando Mazzon Jan 04 '13 at 13:57
  • @FernandoMazzon: Yes, it is the same object and no, it's not a double-registered observer - those were my initial thoughts, but creating a contrived example (where I can be sure that these two possibilities can be discounted) leads to the same results. – sam-w Jan 04 '13 at 14:09
  • 1
    As an aside, you should refer to [Code Naming Basics](https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingIvarsAndTypes.html) for naming conventions. Classes should start with uppercase letters. Properties with lowercase letters. – Rob Jan 04 '13 at 14:11
  • @Rob: Agreed - and +1 for that doc. Our team is mostly C++, however, and we have historical naming conventions which we're required to follow :-/ – sam-w Jan 04 '13 at 14:13
  • 2
    http://stackoverflow.com/questions/4451861/receiving-2-kvo-notifications-for-a-single-kvc-change Here's why – Fernando Mazzon Jan 04 '13 at 14:17
  • @FernandoMazzon: Thanks, that's exactly what I was after. I've voted to close this as a dupe, please do the same if you're so inclined ;-) – sam-w Jan 04 '13 at 14:22

1 Answers1

6

From the docs. If you want manual, you have to override that:

Manual Change Notification

Manual change notification provides more granular control over how and when notifications are sent to observers. This can be useful to help minimize triggering notifications that are unnecessary, or to group a number of changes into a single notification.

A class that implements manual notification must override the NSObject implementation of automaticallyNotifiesObserversForKey:. It is possible to use both automatic and manual observer notifications in the same class. For properties that perform manual notification, the subclass implementation of automaticallyNotifiesObserversForKey: should return NO. A subclass implementation should invoke super for any unrecognized keys. The example in Listing 2 enables manual notification for the openingBalance property allowing the superclass to determine the notification for all other keys.

Fernando Mazzon
  • 3,562
  • 1
  • 19
  • 21
  • 1
    There is a great post on that matter http://petersteinberger.com/blog/2012/dont-call-willchangevalueforkey/ – pronebird Sep 14 '15 at 11:36