我正在尝试在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中的错误?
答案 0 :(得分:15)
您应该在forKeyPath
的{{1}}参数中传递属性的名称,而不是getter或setter:
addObserver
无需使用[self.textView addObserver:self
forKeyPath:@"editable"
options:NSKeyValueObservingOptionNew
context:KVOTestingTestsContext];
和NSStringFromSelector
生成关键路径。事实上,当你这样做时,你可能遇到了你正面临的问题......
密钥路径基于属性的名称,而不是getter。原因是您希望KVO拦截@selector
方法。如果您将setEditable
(无论如何生成)传递给@"isEditable"
,KVO将尝试拦截名为addObserver
的属性的setter,并且此属性不存在。
您使用第二种方法收到通知,因为您最终将isEditable
传递给@"editable"
,这是您想要做的,但您通过引用非现有方法(即addObserver
),因此编译器警告。
由于您无法将getter或setter方法的名称传递给editable
,因此答案是直接使用字符串文字传递属性的名称(即{{1} })。
这是Apple的编程指南供参考:Registering for Key-Value Observing