带有自定义属性getter的KVO通知

时间:2013-11-16 01:16:18

标签: ios objective-c key-value-observing

我正在尝试在iOS中的editable上收听UITextView属性。在UITextView.h的标头中,editable属性定义为:

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

要收听KVO通知,我正在使用addObserver模式,我将keyPath作为NSStringFromSelector(@selector(isEditable))传递,这样如果我使用的是未定义的选择器,Xcode会发出警告。注册isEditable密钥路径时没有任何障碍,但是在更改文本视图上的editable属性后,我从未收到过属性更改的通知。我正在注册观察员:

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

但是,如果我改为使用密钥路径NSStringFromSelector(@selector(editable)),我获取KVO通知,但Xcode会生成警告,表明我使用了未声明的选择器'editable'。

我想知道是否有更好的模式然后我应该使用如果在应该使用自定义getter的情况下发生故障。或者这是Xcode / clang中的错误?

1 个答案:

答案 0 :(得分:15)

您应该在forKeyPath的{​​{1}}参数中传递属性的名称,而不是getter或setter:

addObserver

无需使用[self.textView addObserver:self forKeyPath:@"editable" options:NSKeyValueObservingOptionNew context:KVOTestingTestsContext]; NSStringFromSelector生成关键路径。事实上,当你这样做时,你可能遇到了你正面临的问题......

  1. 密钥路径基于属性的名称,而不是getter。原因是您希望KVO拦截@selector方法。如果您将setEditable(无论如何生成)传递给@"isEditable",KVO将尝试拦截名为addObserver的属性的setter,并且此属性不存在。

  2. 您使用第二种方法收到通知,因为您最终将isEditable传递给@"editable",这是您想要做的,但您通过引用非现有方法(即addObserver),因此编译器警告。

  3. 由于您无法将getter或setter方法的名称传递给editable,因此答案是直接使用字符串文字传递属性的名称(即{{1} })。

  4. 这是Apple的编程指南供参考:Registering for Key-Value Observing