是否可以在 Cocoa Touch 中观察对象的只读属性?
Posted
技术标签:
【中文标题】是否可以在 Cocoa Touch 中观察对象的只读属性?【英文标题】:Is it possible to observe a readonly property of an object in Cocoa Touch? 【发布时间】:2010-10-07 16:08:55 【问题描述】:我试图观察 UINavigationController 的(只读)visibileViewController 属性,但没有成功。我能够成功地观察到我自己定义的用于在另一个类上进行测试的读写属性。
是否可以观察只读属性?
【问题讨论】:
【参考方案1】:是的,可以观察只读属性。但是,如果声明该属性的对象以非 Key-Value Observing compliant 的方式更改该属性的值(例如,直接更改支持该属性的实例变量的值如果没有 seding willChangeValueForKey:
和 didChangeValueForKey:
通知),那么 KVO 系统将不会自动通知观察者。如果您可以验证此属性的值正在更改并且没有通知您的观察者,我会(1)在此处或其他地方发布一些代码,以便其他人可以帮助您找到您的错误,以及(2)如果没有错误您的代码,在 Apple 的 radar 上提交错误。
【讨论】:
那是 NSHipster 忘记的缺失部分。【参考方案2】:是的。在您自己的类中实现它的一种简单方法是在 .h 文件中将该属性声明为只读,并在 .m 文件的私有接口中将其重新声明为可写。这样您就可以合成并自动处理更改通知。
在.h文件中:
@interface MyClass : NSObject
@property (nonatomic, readonly) BOOL foo;
@end
在.m文件中
@interface MyClass ()
@property (nonatomic, readwrite) BOOL foo;
@end
@implementation MyClass
@synthesize foo;
- (void)bar
// Observers will see the change
self.foo = YES;
@end
【讨论】:
我相信这不会停止在这个类之外执行myObject.foo = YES
(除非,也许,ARC 尖叫它看不到声明)
由于合成方法的冲突,我不认为这会起作用,但它似乎对我有用!公开的方法不可用,但我可以私下设置。
这正是如何做到这一点,正如乔伊指出的那样,只需将其设置为私有即可。但请注意,如果您设置了 _foo 并设置了它,那么 KVO 不会触发。【参考方案3】:
您当然可以观察只读属性,但请注意,要使 KVO 工作,您需要符合 KVC 标准——这意味着对属性使用 setter/getter(因为您是只读的,所以您不会获得通过@synthesize
) 或属性的-setValue:forKey:
方法免费设置setter。
【讨论】:
【参考方案4】:一个稍微不同的答案:
@interface MyClass : NSObject
@property (nonatomic, readonly) BOOL foo;
@end
在.m文件中
@interface MyClass ()
@property (nonatomic, readwrite) BOOL foo;
@end
@implementation MyClass
+ (NSSet *)keyPathsForValuesAffectingFoo
return [[NSSet alloc] initWithObjects:NSStringFromSelector(@selector(foo)), nil];
@end
【讨论】:
【参考方案5】:这绝对可以使用NSKeyValueObserving。属性实际上具有 getter/setter 实现,它们只是由编译器通过 Objective-C 类实现中的 @synthesize 关键字为您完成的。由于键值观察协议基于 Objective-C 中的标准 getter/setter 约定,因此观察属性可以正常工作。文档(上面链接)甚至按名称提到了类属性:
“NSKeyValueObserving (KVO) 非正式协议定义了一种机制,允许在其他对象的指定 属性 发生更改时通知对象。”
【讨论】:
只读属性没有setter方法,所以你不能像读写属性一样观察。以上是关于是否可以在 Cocoa Touch 中观察对象的只读属性?的主要内容,如果未能解决你的问题,请参考以下文章
带有嵌入库的 Cocoa Touch Framework Swift