Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

KVO notifications with a custom property getter

I am trying to listen to the editable property on a UITextView in iOS. In the header for UITextView.h, the editable property is defined as:

@property(nonatomic,getter=isEditable) BOOL editable;

To listen for the KVO notification, I'm using the addObserver pattern where I pass the keyPath as NSStringFromSelector(@selector(isEditable)), so that Xcode will warn me if I'm using a selector that isn't defined. Registering for the isEditable keypath goes off without a hitch, but then I never receive a notification that the property changes after changing the editable property on the text view. I'm registering the observer with:

[self.textView addObserver:self
                forKeyPath:NSStringFromSelector(@selector(isEditable))
                   options:NSKeyValueObservingOptionNew
                   context:KVOTestingTestsContext];

However, if I instead use the keypath NSStringFromSelector(@selector(editable)), I do get the KVO notification, but Xcode generates a warning that I am using an undeclared selector 'editable'.

I'm wondering if there is a better pattern then that I should use if this breaks down in the case where one should be using the custom getter. Or is this a bug in Xcode / clang?

like image 663
Streeter Avatar asked Nov 16 '13 01:11

Streeter


People also ask

Can you explain KVO?

KVO, which stands for Key-Value Observing, is one of the techniques for observing the program state changes available in Objective-C and Swift. The concept is simple: when we have an object with some instance variables, KVO allows other objects to establish surveillance on changes for any of those instance variables.

What is KVO in iOS?

Key-value observing is a Cocoa programming pattern you use to notify objects about changes to properties of other objects. It's useful for communicating changes between logically separated parts of your app—such as between models and views. You can only use key-value observing with classes that inherit from NSObject .

What framework is KVO key-value observing a part of?

Key-Value Observing, KVO for short, is an important concept of the Cocoa API. It allows objects to be notified when the state of another object changes.

What is key-value coding and key-value observing?

Using a mechanism called key-value coding (KVC), you can manipulate object properties indirectly. With KVC comes the ability to observe changes to a particular key value, which is known as key-value observing (KVO).


Video Answer


1 Answers

You should be passing the name of the property in the forKeyPath parameter of addObserver, not the getter or setter:

[self.textView addObserver:self
                forKeyPath:@"editable"
                   options:NSKeyValueObservingOptionNew
                   context:KVOTestingTestsContext];

There's no need to generate the key path using NSStringFromSelector and @selector. In fact, when you do so, you potentially run into the problem you're facing...

  1. The key path is based off the name of the property, not the getter. The reason for this is that you want KVO to intercept the setEditable method. If you pass @"isEditable" (no matter how it's generated) to addObserver, KVO will try to intercept the setter for a property called isEditable, and this property does not exist.

  2. You get the notification using your second approach because you end up passing @"editable" to addObserver, which is what you want to do, but you're doing it by referencing a non-existent method (i.e. editable), hence the compiler warning.

  3. Since you can't pass the name of the getter or the setter method to addObserver, the answer is to just pass the name of the property directly using a string literal (i.e. @"editable").

Here's Apple's programming guide for reference: Registering for Key-Value Observing

like image 139
godel9 Avatar answered Sep 22 '22 03:09

godel9