HTBKVObservation 1.3.1

HTBKVObservation 1.3.1

测试已测试
Lang语言 Obj-CObjective C
许可 MIT
发布最后发布2015 年 9 月

Mark Aufflick维护。



  • 作者:
  • Mark Aufflick

HTBKVObservation - 另一个 KVOImprovement 项目

概述

将 HTBKVObservation.m 和 .h 包含在您的项目中

#import "HTBKVObservation.h"

@interface HTBKVOTests ()
@property (strong) HTBKVObservation * anObservation;
@property (strong) NSArray * multipleObservations;
@property (strong) HTBKVObservation * binding;
@property (strong) NSArray * bidirectionalBinding;
@end

@implementation HTBKVOTests

- (void)blockObservation
{
    self.anObservation = [HTBKVObservation observe:anObjectToObserve
                                           keyPath:@"observeMe"
                                           options:0
                                          callback:^(HTBKVObservation *observation, NSDictionary *changeDictionary) {
                                              NSLog(@"observation fired for object: %@ keyPath: %@ changes: %@",
                                                  observation.observedObject,
                                                  observation.keyPath,
                                                  changes);
                                          }];

    self.multipleObservations = [HTBKVObservation observe:anObjectToObserve
                                      forMultipleKeyPaths:@[@"observeMe2", @"observeMe3"]
                                                  options:0
                                             callback:^(HTBKVObservation *observation, NSDictionary *changeDictionary) {
                                                 NSLog(@"observation fired for object: %@ keyPath: %@ changes: %@",
                                                     observation.observedObject,
                                                     observation.keyPath,
                                                     changes);
                                             }];

    self.unidirectionalBinding = [HTBKVObservation bind:theSourceObject
                                                keyPath:@"somePropertyOnTheSourceObject"
                                               toObject:destinationObject
                                                keyPath:@"somePropertyOnTheDestinationObject"];

    self.bidirectionalBinding = [HTBKVObservation bidrectionallyBind:objectA
                                                              keyPath:@"somePropertyOnObjectA"
                                                           withObject:objectB
                                                              keyPath:@"somePropertyOnObjectB"];
}

@end

选项和变更字典均按照正常 KVO 实现。您需要注意避免 block 产生 self 保留循环。

与 MAKVONotificationCenter 等不同,您负责管理 kvo 对象的生命周期 - 当它 dealloc 时,观察将移除。与 MAKVONotificationCenter 类似,使用最小化魔法来 swizzle 观察对象的 dealloc 方法,如果您仍然存在观察(通过关联的 NSHashTable 跟踪)。如果您想了解为什么您持有的 kvo 对象被提前释放,您可以检查 @isValid@ 访问器(您可以使用 KVO 进行观察)。

创建观察对象

在上面的概述中,您可以看到创建观察对象的两种方式,第二种是一次性的便利方式。HTBKVObservation 实例必须保留,以便观察保持活跃(请参阅下面的生命周期部分)。

选项值只是传递给底层 KVO 调用,因此请参阅 NSKeyValueObservingOptions 以获取更多信息。同样,changeDictionary 是 KVO 本身提供的,因此请参阅 observeValueForKeyPath:ofObject:change:context: 以获取更多信息。

创建绑定

当您创建单向绑定时,目标对象将立即同步。

当您创建双向绑定对时,objectB 将与 objectA 同步。随后,objectA 或 objectB 的任何更改都将传播到另一个对象。

观察/绑定生命周期

观察将在调用上述类或便利方法之一时自动开始,或者当您自己创建 HTBKVObservation 实例时,在您发送 observe 消息时。

观察将在下列情况之一发生时结束(清洁)

  1. HTBKVObservation 对象 dealloc
  2. 观察对象 dealloc
  3. 发送 invalidate 消息到 HTBKVObservation 对象。

此外,如果观察对象 dealloc,观察将无效(尽管仍然会触发),因为 HTBObservation 实例仅维护对观察对象的单例引用。

对于单向绑定,以上规则与你预期的一样适用。双向绑定的便利方法仅返回两个 HTBKVObservation 实例,其中一个实例的对象A和对象B是观察者/被观察者在一方或另一方 - 因此,如果对象A或对象B被销毁(当然,如果观察对象被销毁),实际上都会由任一对象结束或失效。

注意事项

  1. 尽管我在多个 Mac 和 iOS 客户端项目中使用了它,但我不能保证广泛的测试。请查看测试应用中的测试,如果您使用的是您认为未被测试的场景,请随时提交拉取请求!
  2. 由版本 0.2 开始,它需要ARC。它在 MacOS 10.8 的测试中最为充分,同时支持 10.7 及以上版本和 iOS 5 及以上版本(为 MacOS 10.7 和 iOS 5 都提供了测试应用)。

运行测试应用

在测试应用从工作空间运行之前,您需要 libextobjc 依赖项。最简单的方法是使用 CocoaPods -只需转到根项目目录并运行pod install。使用此类不需要它。

背景

如果您正在阅读这段内容,那么您可能也和随机出现的 KVO 故障以及观察者中大量 if/else 块带来的痛苦一样感到沮丧。我从未对其他 KVO-改进类感到满意,而且因为我从未有过任何耀眼的洞见,我一直按照常规的方式进行操作。这在与基于视图的 NSTableView 等事物一起使用时显得特别痛苦,当您重复使用对象并需要观察新的对象时,您需要非常小心地取消观察先前的对象(除非它已被释放,这就需要您跟踪它,如果不能,那么保留它,这也存在问题)。

很显然,Mike Ash 的 MAKVONotificationCenter 的 dealloc swizzling 方法是不可避免的,但我不喜欢它的复杂性。最近,Gwynne Raskind 发布了一个相对更新的 MAKVONotificationCenter,这引发了一些讨论,包括一条讨论 SPKVONotificationCenter 的评论,这个类由 Joachim Bengtsson 构建。Joachim 的灵感是观察应该建模为独立对象,并且简单地管理该对象的生命周期应该能够消除观察。简洁而简单。

但这并不完全简单,因为您仍然需要使用观察对象的 dealloc swizzling,因为它们可能随时消失。尽管我像其他黑客一样热爱一个良好的宏,但 Joachim 的 @$depends()@ 宏看起来几乎与能完成任何事情的 makefile 一样有趣。

这就是 HTBKVObservation 出现的原因!

更新记录

  • 0.1 : 为 CocoaPods 用户创建的第一个版本标签
  • 0.2 : 现在需要 ARC,因此保留了目标/操作 API,并增加基于块的 API。
  • 0.3 : 修复了一个可能的竞态条件。
  • 0.4 : 添加了单向绑定。

作者

Mark Aufflick ([email protected]) http://mark.aufflick.com http://htb.io