将 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
消息时。
观察将在下列情况之一发生时结束(清洁)
此外,如果观察对象 dealloc,观察将无效(尽管仍然会触发),因为 HTBObservation 实例仅维护对观察对象的单例引用。
对于单向绑定,以上规则与你预期的一样适用。双向绑定的便利方法仅返回两个 HTBKVObservation 实例,其中一个实例的对象A和对象B是观察者/被观察者在一方或另一方 - 因此,如果对象A或对象B被销毁(当然,如果观察对象被销毁),实际上都会由任一对象结束或失效。
在测试应用从工作空间运行之前,您需要 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 出现的原因!
Mark Aufflick ([email protected]) http://mark.aufflick.com http://htb.io