RACSignal分析
栏目: Objective-C · 发布时间: 5年前
内容简介:信号的使用,包括:创建信号、发送信号、订阅信号获取信号的方式有很多种:最简单的信号是单元信号,有4种:
信号的使用,包括:创建信号、发送信号、订阅信号
创建信号
获取信号的方式有很多种:
-
创建单元信号
-
创建动态信号
-
通过Cocoa桥接
-
从别的信号变换而来
-
由序列变换而来
单元信号
最简单的信号是单元信号,有4种:
// return信号:被订阅后,马上产生一个值事件,同时产生一个完成事件 RACSignal *signal1 = [RACSignal return:someObject]; // error信号:被订阅后,马上产生一个错误事件,同时产生一个完成事件 RACSignal *signal2 = [RACSignal error:someError]; // empty信号:被订阅后,马上产生一个空事件,同时产生一个完成事件 RACSignal *signal3 = [RACSignal empty]; // never信号:永远不产生事件,同时产生一个完成事件 RACSignal *signal4 = [RACSignal never]; 复制代码
动态信号
RACSignal *signal5 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@"1"]; [subscriber sendNext:@"2"]; [subscriber sendCompleted]; return [RACDisposable disposableWithBlock:^{ }]; }];复制代码
Cocoa桥接
RAC为大量的Cocoa类型提供便捷的信号桥接工具,如下是一些常见的桥接方式:
RACSignal *signal6 = [object rac_signalForSelector:@selector(setFrame:)]; RACSignal *signal7 = [control rac_signalForControlEvents:UIControlEventTouchUpInside]; RACSignal *signal8 = [object rac_willDeallocSignal]; RACSignal *signal9 = RACObserve(object, keyPath);复制代码
信号变换
RACSignal *signal10 = [signal1 map:^id(id value) { return someObject; }];复制代码
序列变换
RACSignal *signal11 = sequence.signal;复制代码
订阅信号
订阅信号的方式有3种:
-
通过
subscribeNext:error:completed:
方法订阅 -
RAC宏绑定
-
Cocoa桥接
subscribeNext:error:completed:
是最基础的信号订阅方法;
RAC宏绑定 可以使用 RAC()
宏 如:RAC(view, backgroundColor) = signal;
Cocoa桥接 [object rac_liftSelector:@selector(someSelector:) withSignals:signal1, signal2, nil];
订阅过程
所谓订阅过程指的是信号被订阅的处理逻辑,如下是简单的例子:
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@"1"]; [subscriber sendNext:@"2"]; [subscriber sendCompleted]; return [RACDisposable disposableWithBlock:^{ NSLog(@"dispose"); // 当错误事件或者完成事件产生时,该block被调用 }]; }]; [signal subscribeNext:^(id x) { NSLog(@"next value is : %@", x); } error:^(NSError *error) { NSLog(@"error : %@", error); } completed:^{ NSLog(@"completed"); }];复制代码
信号的各类操作
RACTuple , 就像NSArray数组:
RACTuple *tuple = RACTuplePack(@1, @"haha"); id first = tuple.first; id second = tuple.second; id last = tuple.last; id index1 = tuple[1]; RACTupleUnpack(NSNumber *num, NSString *str) = tuple; 复制代码
信号的操作一般分为单个信号的变换、多个信号的组合及高阶操作
单个信号的变换
分为值操作、数量操作、时间操作、副作用操作
值操作
map 做一个映射,返回新的信号
mapReplace 等价于返回同一个值得map
reduceEach,是map:的变体。当signalA的值事件包裹的数据是RACTuple类型时,才可以使用该操作,将RACTuple组合成一个
reduceApply,要求值事件包裹的数据类型是RACTuple,并且该RACTuple的第一个元素是一个block,后面的元素作为该block的参数传入,返回该block的执行结果。
逻辑操作:not, and, or
数量操作
filter 过滤
ignore 忽略
take 只取前n个
skip 过滤掉前n个
startWith 从某个元素开始
distinctUntilChanged 去重复
repeat 重复
retry [signalA retry:2]; 重试几次
collect 把所以集合到一个
aggregate 和sacn 类似但有区别 scan 实时输出,aggregate 最终结束才输出,出错则不输出
副作用操作
doNext doError doCompleted
initially finally
时间操作
delay 延迟
throttle:1 当signalA事件流产生一个值事件时,若1 s内没有其他的值事件产生,则signalB事件流中也会产生该值事件;当signalA事件流产生一个值事件时,若1s内有其他的值事件产生,则signalB会过滤掉该值事件,对于signalA中的最后一个值事件,signalB事件流中总会也包含它
多个信号的组合
concat 加在后面
merge 插入进来
zip 两个信号合成一个RACTuple
combineLatest a信号来一个值事件就和b信号最近的值事件组合
sample 类似取景和快门
takeUntil signalC事件流中的事件和signalA一一对应,直到signalB事件流中出现了信号,事件流就终结。
信号的高阶操作
switchToLatest 读到新的信号就把之前的信号关闭
if then else 其实就是switchToLatest的实现
+ (RACSignal *)if:(RACSignal *)boolSignal then:(RACSignal *)trueSignal else:(RACSignal *)falseSignal { ..... return [[[boolSignal map:^(NSNumber *value) { NSCAssert([value isKindOfClass:NSNumber.class], @"Expected %@ to send BOOLs, not %@", boolSignal, value); return (value.boolValue ? trueSignal : falseSignal); }] switchToLatest] setNameWithFormat:@"+if: %@ then: %@ else: %@", boolSignal, trueSignal, falseSignal]; }复制代码
代替代理
-
rac_signalForSelector
用于代替代理
代替 KVO
-
rac_valuesAndChangesForKeyPath
用于监听某个对象的某个属性的改变
代替事件监听
-
rac_signalForControlEvents
用于监听某个事件
代替通知
-
rac_addObserverForName
用于监听某个通知,且不需要在- (void)dealloc
中移除监听
监听文本框文字改变
-
rac_textSignal
用于监听文本框文字变化
监听手势
-
rac_gestureSignal
用于监听手势操作
多个请求完成时,再执行后继操作
-
rac_liftSelector:withSignalsFromArray:Signals
当传入的 Signals,每一个 Signal 都至少 sendNext 过一次,就会去触发第一个 selector 参数的方法。
信号的相关操作
-
bind
:函数会返回一个新的信号 N。整体思路是对原信号 O 进行订阅,每当信号 O 产生一个值就将其转变成一个中间信号 M ,并马上订阅 M ,之后将信号M的输出作为新信号 N 的输出。 -
map
\flattenMap
:用于把源信号内容映射成新的内容(信号)。 -
concat
:组合,按一定顺序拼接信号,当多个信号发出的时候,有顺序的接收信号。 -
then
:用于连接两个信号,当第一个信号完成,才会连接then
返回的信号。 -
merge
:把多个信号合并为一个信号,任何一个信号有新值的时候就会调用。 -
zipWith
:把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,并且把两个信号的内容合并成一个元组,才会触发压缩流的next
事件。 -
combineLatest
:将多个信号合并起来,并且拿到各个信号的最新的值,必须每个合并的signal
至少都有过一次sendNext
,才会触发合并的信号。 -
reduce
:聚合,用于信号发出的内容是元组,把信号发出元组的值聚合成一个值。 -
filter
:过滤信号,使用它可以获取满足条件的信号。 -
ignore
:忽略某些值的信号,使用RACObserve
时可配合使用,其实现由filter
完成。 -
distinctUntilChanged
:实现是用bind
来完成的,每次变换中都记录一下原信号上一次发送过来的值,并与这一次进行比较,如果是相同的值,就「吞」掉,返回 empty 信号。只有和原信号上一次发送的值不同,变换后的新信号才把这个值发送出来。 -
take
:从开始一共取 N 次的信号。 -
takeLast
:取最后 N 次的信号,前提条件:订阅者必须调用完成,因为只有完成,才知道总共有多少信号。 -
takeUntil
:获取信号直到某个信号执行完成。 -
skip
:跳过几个信号,不接受。 -
switchToLatest
:用于signalOfSignals
(信号的信号),有时候信号也会发出信号,会在signalOfSignals
中,获取signalOfSignals
发送的最新信号。 -
doNext
:执行next
之前,会先执行这个 Block 。 -
doCompleted
:执行sendCompleted
之前,会先执行这个Block 。 -
timeout
:超时,可以让一个信号在一定的时间后,自动报错。 -
interval
:定时:每隔一段时间发出信号。 -
delay
:延迟发送next
。 -
retry
:重试,只要失败,就会重新执行创建信号中的 block ,直到成功。 -
replay
:重放,当一个信号被多次订阅,反复播放内容。 -
throttle
:节流,当某个信号发送比较频繁时,可以使用节流,在某一段时间不发送信号内容,过了一段时间获取信号的最新内容发出。
ReactiveCocoa 常见宏
-
RAC(TARGET, ...)
用于绑定某个对象的某个属性 -
RACObserve(TARGET, KEYPATH)
用于监听某个对象的某个属性,返回的是信号 -
@weakify(Obj)
&@strongify(Obj)
配套使用
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 使用动态分析技术分析 Java
- 使用动态分析技术分析 Java
- 案例分析:如何进行需求分析?
- 深度分析ConcurrentHashMap原理分析
- 如何分析“数据分析师”的岗位?
- EOS源码分析(3)案例分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。