前言
一直想找一个方便使用的可以替代消息通知的通信工具,可以避免再编写繁琐的 Delegate 接口。偶然在项目中接触了 RAC框架(ReactiveCocoa),响应式编程 + 链式编程,功能的确很强大,但是也遇到过很多问题,踩过很多坑,每次解决成本都很高,学习成本太高,需要掌握很多细节特性才能用好。而且 RAC 属于大型框架,对项目代码侵入性很大。另外不适用于制作对外接口,假如要开发一个 SDK 给其他项目使用的话,总不能要求使用者都同样使用 RAC 吧。但是一直找不到一个简单的轻量级通信工具,于是自行编写了一个小工具 XKVO。
如果你不想继续使用RAC这种大型框架,又想从繁重的通信接口中解脱出来,那么本文描述的XKVO工具或许就能解决你的问题了。
XKVO介绍
轻量级通信工具 使用 Block 的方式实现一对多的事件通知,使用Block封装系统KVO方法,让监听属性变化变得非常简单
XKVO 分为两个部分,准确的说,其实只有两个类:
-
XSimpleSignal
XSimpleSignal - 轻量级简易信号通知工具,使用Block来代替Delegate与Notification,支持一对多通信信号-Block管理, 使用时创建一个 XSimpleSignal 对象,监听者拿到这个对象,向该信号注册监听Block,一个信号对象(XSimpleSignal)可以注册多个监听者,当有事件发生的时候,信号对象的Owner调用 signal.emitSignal(id, ...)发送信号,各监听者便能收到通知,先注册者先到达。
-
XSimpleKVO
使用 XSimpleSignal 来封装系统的 KVO 方法,使用者可以使用 Block 来监听 KVO 的回调,简单易用。
用法举例
安装教程
1. 在 Podfile 中引入 XKVO:
pod 'XKVO', :git => 'https://gitee.com/fireice2048/xkvo.git', :branch => 'master'
2. 执行 pod install
复制代码
KVO属性监听
- #import <XKVO/XKVO.h>
- 添加KVO监听代码
@interface ViewController ()
@property (nonatomic, assign) NSInteger testCount;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[XKVO xkvo_addObserverForObject:self property:@"testCount" changedBlock:^(id _Nonnull oldValue, id _Nonnull newValue, BOOL isInitialNotify) {
NSLog(@"监听到 testCount 属性变化 %@ ==> %@", oldValue, newValue);
}];
self.testCount ++;
}
@end
复制代码
- 运行程序,会看到如下日志输出:
监听到 testCount 属性变化 0 ==> 1
复制代码
- 将监听代码添加 initialNotify:YES,
[XKVO xkvo_addObserverForObject:self property:@"testCount" changedBlock:^(id _Nonnull oldValue, id _Nonnull newValue, BOOL isInitialNotify) {
NSLog(@"监听到 testCount 属性变化 %@ %@ ==> %@", isInitialNotify ? @"初始值" : @"", oldValue, newValue);
} initialNotify:YES];
复制代码
运行程序,会看到如下日志输出:
监听到 testCount 属性变化 初始值 0 ==> 0
监听到 testCount 属性变化 0 ==> 1
复制代码
initialNotify : 初始值是否回调block通知,默认为 NO。由于iOS的KVO在监听到变化前,拿不到即将变化的新值,所以没必要实现 priorNotify isInitialNotify : YES 表示该次监听回调的是当前的值,并非变更事件,此时 newValue 跟 oldValue 是相同的值
信号发送与监听
- #import <XKVO/XKVO.h>
@property (nonatomic, strong) XSimpleSignal * loginSignal; // 登录信号
复制代码
- 创建信号对象
_loginSignal = [[XSimpleSignal alloc] init];
复制代码
- 添加信号监听代码
[_loginSignal addBlock:^(NSString * nick, int age){
NSLog(@"监听者1号 收到账号登录事件 nick:%@, age:%@", nick, @(age));
}];
[_loginSignal addBlock:^(NSString * nick, int age){
NSLog(@"监听者2号 收到账号登录事件 nick:%@, age:%@", nick, @(age));
}];
[_loginSignal addBlock:^(NSString * nick, int age){
NSLog(@"监听者3号 收到账号登录事件 nick:%@, age:%@", nick, @(age));
}];
复制代码
- 添加信号发送代码
if (_loginSignal)
{
_loginSignal.emitSignal(@"小白菜", 20);
}
复制代码
运行程序,会看到如下日志输出:
监听者1号 收到账号登录事件 nick:小白菜, age:20
监听者2号 收到账号登录事件 nick:小白菜, age:20
监听者3号 收到账号登录事件 nick:小白菜, age:20
复制代码
三个监听者都收到了账号登录事件。
注意事项
- 添加的各block必须类型一致
- 发送信号的时候,各参数需要跟添加的block一致
- 第一个参数必须是id类型,所以block必须有至少一个参数