使用 blocks 轻松实现 Key-Value Observing。
这是一个 Key-Value Observation 机制扩展,允许您使用 blocks 作为观察处理器。Block Observing 可以与经典 KVO 一起使用而不会出现任何问题。
您应该熟悉 Key-Value Observing 和 Key-Value Coding 的概念。
本项目中的库和示例应用是针对 iOS 的,但您也可以通过直接导入源文件在 OS X 项目中使用。
__weak
)libBlockObserving.a
添加到 链接二进制与库。-ObjC
和 -all_load
作为 构建设置 中的 其他链接器标志。Libraries/**
)。MTKObserving.h
导入您的文件(通常在 Prefix.pch
中)。任何对象都可以使用 block 处理器来观察 它自己的 key-path。调用者和接收者必须是相同的对象,并且 key-path 必须相对于接收者。
[self observe:@keypath(self.profile.username) withBlock:
^(__weak typeof(self) self, NSString *oldUsername, NSString *newUsername) {
self.usernameLabel.text = newUsername;
}];
Block 参数没有特定的类型(所以它们是 id
)。您应该根据需要自行指定类型。原始值-wrap 在 NSNumber
或 NSValue
实例中。
以上代码示例使用了提供的宏
MTKObservePropertySelf(profile.username, NSString *, {
self.usernameLabel.text = newUsername;
});
注意:这与标准 KVO 不同。
一旦观察属性值发生变化,但如果这些值是相等的(使用-isEqual:
方法),则观察块将不会调用。例如self.title = self.title;
不会触发观察。
所有观察块的第一个参数是接收者/调用者,名称为self
。它覆盖了方法参数self
,但包含相同的对象。唯一的区别是__weak
属性。在上面的示例代码中,你可以使用self
而不会引起保留循环。
如果你想跳出当前作用域,只需提供选择器而不是代码块。
[self observe:@keypath(self.profile.username) withSelector:@selector(didChangeUsernameFrom:to:)];
有些方法接收一个关键路径数组和一块(或选择器)。
将属性映射到另一个属性。一旦源关键路径发生变化,目的地会使用新值进行更新。按您想要的任何方式转换值。
[self map:@keypath(self.profile.isLogged) to:@keypath(self.isLoggedLabel.text) transform:
^NSString *(NSNumber *isLogged) {
return (isLogged.boolValue ? @"Logged In" : @"Not Logged In");
}];
此外,还有一个指定空值替换的便利方法。
[self map:@keypath(self.profile.username) to:@(self.usernameLabel.text) null:@"Unknown"];
通过使用两个单程绑定可以实现双向绑定。别担心递归,因为如果值相等,将抑制观察。通过这种方式,您可以映射user.name
到textField.text
,这样它将始终显示名称,然后映射textField.text
到user.name
以在用户更改后更新名称。
通过块改进了通知的观察。NSNotificationCenter
提供了一些支持,但在这里您不必担心移除那些块或保留循环。
MIT许可证,版权(c)2012-2013马丁·基斯
软件按“原样”提供,等等……