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

Str*_*ter 11 objective-c key-value-observing ios

我想在iOS editable上听一下这个属性UITextView.在标题中UITextView.h,editable属性定义为:

@property(nonatomic,getter=isEditable) BOOL editable;
Run Code Online (Sandbox Code Playgroud)

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

[self.textView addObserver:self
                forKeyPath:NSStringFromSelector(@selector(isEditable))
                   options:NSKeyValueObservingOptionNew
                   context:KVOTestingTestsContext];
Run Code Online (Sandbox Code Playgroud)

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

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

god*_*el9 15

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

[self.textView addObserver:self
                forKeyPath:@"editable"
                   options:NSKeyValueObservingOptionNew
                   context:KVOTestingTestsContext];
Run Code Online (Sandbox Code Playgroud)

没有必要使用NSStringFromSelector和生成密钥路径@selector.事实上,当你这样做时,你可能遇到了你所面临的问题......

  1. 关键路径基于属性的名称,而不是getter.原因是你希望KVO拦截该setEditable方法.如果你传递@"isEditable"(无论它是如何生成的)addObserver,KVO将尝试拦截被调用属性的setter isEditable,并且此属性不存在.

  2. 您使用第二种方法获得通知,因为您最终会传递@"editable"给您addObserver,这是您想要做的,但您通过引用不存在的方法(即editable)来执行此操作,因此编译器警告.

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

这是Apple的编程指南供参考:注册键值观察