说 RACSignal
是 RAC
中的核心并不过分,这个框架的本质就是信号的产生,分发与订阅。
“A signal, represented by the RACSignal class, is a push-driven
stream.”
官方文档介绍中有说 signal
是 push-driven
的,但信号在没有订阅者的时候是 cold
状态,只有被订阅后才变成 hot
并开始分发。也就是常说的冷信号与热信号。
大神 sunnyxx 把这种现象生动的比喻成巧克力工厂,生产一个吃一个。有订单才生产,没有订单就不开工。
// 创建一个基本 signal
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@1];
[subscriber sendNext:@2];
[subscriber sendCompleted];
return nil;
}];
这样没人订阅什么也不会发生,block
里面的代码并没有执行。
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@", x);
}];
有人订阅(有了订单)后信号被激活,发一个就收到一个(生产一个吃一个巧克力)。
2017-04-18 11:46:04.717 simpleRacDemo[15054:2153646] 1
2017-04-18 11:46:04.717 simpleRacDemo[15054:2153646] 2
2017-04-18 11:46:04.717 simpleRacDemo[15054:2153646] dispose
一共生产了两块巧克力。
最基本的 next、completed,error
[signal subscribeNext:^(id x) {// 信号产生的值
NSLog(@"x = %@", x);
} error:^(NSError *error) {// 错误返回
NSLog(@"error = %@", error);
} completed:^{// 信号成功结束,不带值
NSLog(@"completed");
}];
当信号成功结束后会 dispose
表明自己已经被了结。
map 映射
map
这个概念在很多语言都有,在 RAC
中会把 signal
发送来的值逐个过滤一次,输出新的目标序列。
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
[subscriber sendNext:@1];
[subscriber sendNext:@2];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"dispose");
}];
}];
[[signal map:^id _Nullable(id _Nullable value) {
return [value isEqual:@1] ? @1 : @"not equal";
}] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
2017-04-18 15:05:27.185 simpleRacDemo[15463:2436314] 1
2017-04-18 15:05:27.186 simpleRacDemo[15463:2436314] not equal
2017-04-18 15:05:27.186 simpleRacDemo[15463:2436314] dispose
当收到 @2
时经过我们三目运算的处理打印了 not equal
。
filter 过滤
这个看名字就会了解是过滤掉不符合条件的返回值
稍微改一下上面的订阅
[[signal filter:^BOOL(id _Nullable value) {
return [value isEqual:@1];
}] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
2017-04-18 15:10:57.899 simpleRacDemo[15515:2461820] 1
2017-04-18 15:10:57.900 simpleRacDemo[15515:2461820] dispose
只有 1 满足条件
以上是十分常用的方法,RAC 中的其它方法还有很多。可以根据相应的业务场景深入研究。
take — takeLast/takeUntil/takeWhileBlock
最基本的使用就是拿,后面参数是 NSInteger
,代表了拿前这么多个值。
skip — skipWhileBlock/skipUntilBlock
相对应的跳过前 n 个值。
repeat/repeatWhileBlock
重复发送信号
delay
延迟发送
throttle 节流
[[[self.textFild rac_textSignal] throttle:0.5] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
文本输入变化很多,限制0.5秒无变化才响应。
distinctUntilChanged
[[[self.textFild rac_textSignal] distinctUntilChanged] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
相应的不发送两次相同的请求,有变化才响应。
timeout 超时
ignore
还是把上面的订阅修改一下,忽视 @1。
[[signal ignore:@1] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
2017-04-18 15:44:51.597 simpleRacDemo[15975:2565685] 2
2017-04-18 15:44:51.597 simpleRacDemo[15975:2565685] dispose
如同期望只剩下了 @2。
小结
-
RACSignal
是有副作用的,在上一篇文章中有过简单理解。ReactiveCocoa 冷热信号 - - RAC 的英文名名已经十分的精准,翻译成中文反而影响理解,尽量看方法名和注释理解意图。
- RAC 持续学习更新中,作为个人的笔记同时也分享给大家,有错误的地方,欢迎大家批评指正,共同探讨。
参考资料:
- Reactive Cocoa Tutorial 3 = RACSignal的巧克力工厂 · sunnyxx的技术博客
- 探究RAC-RAC信号处理方法归纳 – cbs->fffffly