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?
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.
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 .
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.
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).
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...
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With