KVO 订阅��式受 FBKVOController 和 MAKVONotificationCenter 启发,兼容回 iOS5。
您需要保证最低部署目标为 iOS 5.0+ 或 OSX 10.7+,且运行于 ARC 环境下,或者知道如何选择性地在特定文件中启用 ARC。
以下是配置 ZCRMailbox 运行的方法
在选项的海洋中迷失?强烈建议您使用 Cocoapods!
无论您选择哪种方法,您都可以通过在需要的位置导入 ZCRMailbox 来开始使用它
#import "ZCRMailbox.h"
此项目中只有一个文件: ZCRMailbox.h 和 ZCRMailbox.m。您可以通过克隆仓库并将它们从 Classes
目录拖入您的 Xcode 项目中找到它们。请确保勾选了“将项目在本目标文件夹中复制的选项(如果需要)”复选框以及需要使用的任何目标。哦,如果不巧文件名冲突,您可能需要重命名文件。
热爱框架?克隆仓库,然后在 Xcode 中打开 Project/ZCRMailbox.xcodeproj
。将目标更改为 Framework
并构建。导航到组织者并找到“项目”选项卡中的 ZCRMailbox 项目。点击旁边微小的箭头,以在 Finder 中打开“衍生数据”文件路径。正确的文件夹应该会被突出显示,并命名为类似于 ZCRMailbox-<GOBBLEDYGOOK>
的东西。导航进入那里,然后在 Build/Products/Release-<PLATFORM>
中,最后您应该看到 ZCRMailbox.framework
。好了。
庆祝一下,然后把这个框架拖到更容易找到的地方。
现在您有了一个打包好的框架,您可以把它拖进您的项目,压缩并分享给朋友,或者只是留着玩玩。
使用订阅者创建一个 ZCRMailbox
ZCRMailbox *mailbox = [[ZCRMailBox alloc] initWithSubscriber:subscriber]
因为订阅者只有弱引用,所以订阅者持有其邮箱是个好主意
self.mailbox = [[ZCRMailbox alloc] initWithSubscriber:self];
如果您需要将通知消息发送到特定队列的订阅者,您也可以这么做
self.mailbox.messageQueue = [NSOperationQueue mainQueue];
一旦你有了邮箱,你就可以开始添加对象的订阅,称为通知器。
NSKeyValueObservingOptions options = NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew;
[self.mailbox subscribeTo:newsletter keyPath:@"updatedDate" options:options block:^(ZCRMessage *message) {
// Do something
}];
你可以添加任意多个通知器和键路径的订阅,所有这些都可以从一个邮箱中进行!
如果你更喜欢选择器而不是块,可以尝试以下之一
[self.mailbox subscribeTo:newsletter keyPath:@"updatedDate" options:options selector:@selector(newsletterDidUpdateDate)];
[self.mailbox subscribeTo:newsletter keyPath:@"posts" options:options selector:@selector(newsletterDidUpdatePost:))];
...
- (void)newsletterDidUpdateDate { // Do stuff }
- (void)newsletterDidUpdatePost:(ZCRMessage *)message { // Do stuff }
最后,如果你正在迁移传统的KVO代码,并希望有一个快速的插件式解决方案,直到你能够使用选择器和块,这里有这个
static void *ABCSubscriberKVOContext = &ABCSubscriberKVOContext;
...
[self.mailbox subscribeTo:newsletter keyPath:@"updatedDate" options:options context:ABCSubscriberKVOContext];
...
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == ABCSubscriberKVOContext) {
// Optionally convert this to a message
ZCRMessage *message = [[ZCRMessage alloc] initWithNotifier:object keyPath:keyPath change:change];
// Do something
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
不是很好看,但必要时可以替代。上下文是可选的,但传统上这是一个很好的主意,以确保你接收到的通知是你想要的。
当你用完邮箱后,你可以简单地让它自行释放。这将自动取消所有订阅。
如果你需要取消订阅但仍想使用邮箱,你可以使用取消订阅方法
[self.mailbox unsubscribeFrom:newsletter keyPath:@"updatedDate"];
[self.mailbox unsubscribeFrom:newsletter];
[self.mailbox unsubscribeFromAll];
ZCRMailbox使用XCTest编写单元测试,并使用Travis CI进行持续集成。要自己运行测试,首先克隆仓库。然后,你可以从Xcode内部或从命令行运行测试。
打开Project/ZCRMailbox.xcodeproj
并确保方案设置为"ZCRMailbox"。通过从顶部菜单选择Product/Test
或使用快捷键CMD+U
来运行测试。
首先安装xctool。然后从项目目录内运行rake test
。
想要了解更多关于制作香肠的细节吗?本节将讨论ZCRMailbox的一些实现细节。
ZCRMailbox
对订阅者进行弱引用,并维护一个以_ZCRSubscription
对象的集合为键的强引用通知器的字典。_ZCRSubscription
对创建它的ZCRMailbox
和其他KVO观察的详细内容进行弱引用。ZCRMailbox
会推迟到共享所有邮箱的_ZCRPostOffice
。_ZCRPostOffice
实际上处理所有的KVO观察和观察消除,以确保线程安全。它维护一个由ZCRMailbox
实例发出的_ZCRSubscription
对象集合。NSRecursiveLock
实例来维持线程安全。_ZCRPostOffice
处理,因此可以在不同的线程上创建ZCRMailbox
实例、订阅和取消订阅,而无需担心。由于KVO订阅和取消订阅需要同步执行,因此在这里使用了简单的锁定机制,而不是使用具有多个读者和单个写者的派发队列。如果每个《ZCRMailbox》实际处理自己的KVO通知,这不会成为问题,因为单个邮箱不会接收到大量订阅或取消订阅。然而,为了防止在观察的生命周期之后出现僵尸KVO更新,所有更新都通过共享的《_ZCRPostOffice》传递,该系统必须同步处理所有订阅。如果所有《ZCRMailbox》实例中发生大量的订阅和取消订阅操作,则可能会造成瓶颈。这种做法的实际情况尚不明确,如果你遇到性能问题,建议对相关的类进行性能分析。