什么时候使用KVO?

时间:2013-06-09 08:04:09

标签: objective-c key-value-observing

我已经阅读了很多关于KVO的文档,但我仍然对何时使用它感到困惑。

如果objA想要监控objB的某个属性,请执行以下操作:

self.objB = [[ObjB alloc] init];
[self.objB addObserver:self
            forKeyPath:@"address"
               options:0
               context:nil];

因此,如果objB的属性发生变化,并且只能由self更改,那么为什么不这样做呢?

self.objB.property = @"newValue";
[self doSomethingBasedOnNewValueOfObjBnewProperty];

而不是

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context

{
    if(keyPath == @"address") {
        [self doSomethingBasedOnNewValueOfObjBnewProperty];
    }
}

与单身一起使用时可能很有用,例如self.objB = [ObjB sharedInstance],其中属性可能会被其他对象更改。这是唯一的用例吗?

2 个答案:

答案 0 :(得分:17)

并非所有类的所有实例都只由同一个实例创建和编辑(这实际上就是您的示例所示)。

KVO是一种通用方法,通过该方法,一个实例可以观察另一个实例的更改并接收已发生事件的通知。这些变化可以从任何地方触发。

假设您在项目中添加了第三方库。你不知道它是如何实现的。调用一个方法可以更改库类实例中的多个不同属性。 KVO为您提供了一种监控和应对这些变化的简便方法。

KVO还提供“Dependent Keys”,它允许您配置键之间的关系,因此您可以说“此属性的值取决于另一个对象中一个或多个其他属性的值”,KVO会告诉您何时发生。这在托管对象子类中尤其有用,例如,如果您有一个临时密钥,该密钥保存某个持久密钥的缓存值,并且只要持久值发生更改,就需要更新缓存...

答案 1 :(得分:11)

Wain的答案是完美的。我想通过陈述KVO可能用途的一些例子来做出贡献。

KVO可用于某些对象"说一个或多个视图控制器"需要监控许多对象的变化。

例如, FPS游戏有一些视图,一个显示玩家彼此之间的互动,一个角落上的视图显示当前玩家得分和健康;以及显示玩家的菜单'点击按钮或暂停游戏时得分。 如果当前玩家被其他玩家击中或被其他玩家击中,则需要更新主视图,显示成功击中或显示玩家受伤的迹象,分数和健康状况视图需要更新其数据和玩家的分数视图需要更新。现在假设您需要添加一个新的控制器对象来监控玩家的成就,方法是监控他的得分和他的杀人次数。此对象还需要通知播放器发生的任何事件。

在这种情况下,许多物体需要监视许多其他物体的变化"当前玩家和其他玩家"。 KVO为您提供了一个简单的工具来实现这个,而无需编写代码来处理通知注册和实际通知。想想如何从头开始实现它以注意差异。


在另一个例子中,我通常倾向于为web服务检索的一些数据一个singelton加载器。在这种情况下,应用程序的许多部分都需要一些数据。

例如,您希望开发由商店制作的应用,向用户显示可用商品。此应用需要向用户显示显示所有项目的表格视图,显示特定类别的项目的视图,显示待售商品的其他视图< / strong>,另一个显示详细信息和特定商品的可用数量的视图。 现在假设应用程序需要每隔几个小时或用户请求刷新时刷新数据。该loader类可以自己处理刷新操作,视图控制器可以注册到相关的键。这样,刷新在一个对象中处理,其他对象可以只关注它们的视图处理逻辑。