Search code examples
ioskey-value-observing

KVO for manually implemented properties


According to Ensuring KVC Compliance,

For properties that are an attribute or a to-one relationship, this requires that your class:

  • Implement a method named -<key>, -is<Key>, or have an instance variable <key> or _<key>.

What is the best way to add observers to "FAKE" properties like the following?

@property (nonatomic, readonly) BOOL shortlisted; 

#pragma mark - Fake properties

- (BOOL)shortlisted
{
    return [self.provider isJobShortlisted:self];
}   

Solution

  • Dependent Keys

    If you simply have one key which is dependent on another key of the same object, you can override +keyPathsForValuesAffectingValueForKey:. (See also this article for a common pitfall.)

    The KVO documentation has information about keys dependent on other objects, but unfortunately it looks like this only has built-in support on OS X (not iOS).

    Manual Notifcations

    If you're implementing a completely custom property, the section on Manual Change Notification in the KVO docs has all the information you need. The key points are (with quotes from the docs):

    • A class that implements manual notification must override the NSObject implementation of automaticallyNotifiesObserversForKey:. ... For properties that perform manual notification, the subclass implementation of automaticallyNotifiesObserversForKey: should return NO.

    • To implement manual observer notification, you invoke willChangeValueForKey: before changing the value, and didChangeValueForKey: after changing the value.

      (If you change multiple properties, you can nest these calls.)

    • In the case of an ordered to-many relationship, you must specify not only the key that changed, but also the type of change and the indexes of the objects involved.

      For this you use the methods willChange:valuesAtIndexes:forKey: and didChange:valuesAtIndexes:forKey:.