一、信号合并
(1)信号合并_Merge
/// 【多个信号合并】- 1
/// 只要其中一个信号有信号,就会触发
/// 场景:适合多个事件的处理流程相同。比如有多个按钮的触发事件都是跳转下一页
-(void)merge {
RACSubject * signalA = [RACSubject subject];
RACSubject * signalB = [RACSubject subject];
RACSubject * signalC = [RACSubject subject];
///两个信号组合信号
RACSignal * mergeSignal = [signalA merge:signalB];
[mergeSignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
/// 多个信号组合
RACSignal * mulitSignal = [RACSignal merge:@[signalA,signalB,signalC]];
[mulitSignal subscribeNext:^(id _Nullable x) {
NSLog(@"mergeSignal : %@",x);
}];
/// 发送信号---交换位置则数据结果顺序也会交换
[signalC sendNext:@3];
[signalB sendNext:@2];
[signalA sendNext:@1];
}

(2)信号合并_CombineLatest
/// 【多个信号合并】- 2
/// 将多个信号合成一个信号,只有每个信号都触发过,才会合成一个信号触发
/// 场景:在需要满足某种条件下,才能执行下一步。比如登录,只有输入账号密码,之后才能提交
/// 备注:还有另外一个常用方法:combineLatest:reduce:
- (void)combineLatest {
RACSubject * signalA = [RACSubject subject];
RACSubject * signalB = [RACSubject subject];
RACSubject * signalC = [RACSubject subject];
/**
[[RACSignal combineLatest:@[signalA,signalB,signalC]] subscribeNext:^(RACTuple * _Nullable x) {
NSNumber *a = x.first;
NSNumber *b = x.second;
NSString *c = x.third;
NSLog(@"最终结果:a:%@,b:%@,c:%@",a,b,c);
}];
*/
[[RACSignal combineLatest:@[signalA,signalB,signalC] reduce:^id _Nonnull(NSNumber *a,NSNumber *b,NSString *c){
/// reduce可以将合并后的信号RACTuple元祖的值都取出来,
/// 然后做一些操作,再合成一个另外一个值返回出去
NSString *resutl = [NSString stringWithFormat:@"最终结果:a:%@,b:%@,c:%@",a,b,c];
return resutl;
}] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[signalC sendNext:@"3"];
[signalB sendNext:@2];
[signalA sendNext:@1];
}

(3)信号合并_concat
/// 【多个信号合并】- 3
/// 按顺序拼接信号,按顺序接收信号,必须等上一个信号完成sendCompleted,下个信号才有用。类似于同步
/// 场景:信号之间有依赖关系的。比如下载解压,只有下载成功后才能解压
- (void)concat {
RACSubject * signalA = [RACSubject subject];
RACSubject * signalB = [RACSubject subject];
[signalA subscribeNext:^(id _Nullable x) {
[signalA sendCompleted];
}];
[signalB subscribeNext:^(id _Nullable x) {
}];
/// 必须singnalA信号sendCompleted之后,才能接收signalB 的信号
[[signalA concat:signalB] subscribeNext:^(id _Nullable x) {
NSLog(@"下载解压完成");
}];
/// 打印结果:下载解压完成
[signalA sendNext:@"下载"];
[signalB sendNext:@"解压"];
/// 打印结果为空
/// [signalB sendNext:@"解压"];
/// [signalA sendNext:@"下载"];
}
(4)信号合并_then
/// 【多个信号合并】- 4
/// 按顺序拼接信号,按顺序接收,必须等上一个信号完成sendCompleted,下个信号才有用。
/// 与concat功能类似,多了第一个信号完成后能额外执行其他代码,再出发第二个信号
/// 场景:信号之间有依赖关系的。比如下载解压
- (void)then {
RACSubject * signalA = [RACSubject subject];
RACSubject * signalB = [RACSubject subject];
[signalA subscribeNext:^(id _Nullable x) {
[signalA sendCompleted];
}];
[signalB subscribeNext:^(id _Nullable x) {
}];
/// 必须singnalA信号sendCompleted之后,才能接收signalB 的信号
[[signalA then:^RACSignal * _Nonnull{
NSLog(@"下载完成,数据拼接");
return signalB;
}] subscribeNext:^(id _Nullable x) {
NSLog(@"下载解压完成");
}];
/// 打印结果:
/// 下载完成,数据拼接
/// 下载解压完成
[signalA sendNext:@"下载"];
[signalB sendNext:@"解压"];
/// 打印结果:下载完成,数据拼接
/// [signalB sendNext:@"解压"];
/// [signalA sendNext:@"下载"];
}
(4)信号合并_zipWith
/// 【多个信号合并】- 5
/// 把两个信号压缩成一个信号,只有当两个信号同时发出信号时,将两个信号的内容合并成一个元祖,触发压缩信号
/// 与combineLatest作用类似
/// 场景:在需要满足某种条件下,才能执行下一步。比如当一个界面有多个请求的时候,要等所有请求完成才能更新UI
- (void)zipWith {
RACSubject * signalA = [RACSubject subject];
RACSubject * signalB = [RACSubject subject];
RACSignal * zipSignale = [signalA zipWith:signalB];
[zipSignale subscribeNext:^(RACTuple *x) {
NSLog(@"下载解压完成:%@ %@",x.first,x.second);
}];
/// 打印结果:
/// 下载完成,数据拼接
/// 下载解压完成
[signalA sendNext:@"下载"];
[signalB sendNext:@"解压"];
}
(5)信号合并_liftSelector
/// 【多个信号合并】- 6
/// 当信号组的每个信号都发送过信号(sendNext:才算,而sendError:不算),就会触发关联的方法selector;
/// 信号数组的个数与selector的参数数量一一对应
/// 场景:一个界面有多个接口,需要都获取数据后,才刷新界面
- (void)liftSelector {
RACSubject * signalA = [RACSubject subject];
RACSubject * signalB = [RACSubject subject];
RACSubject * signalC = [RACSubject subject];
[self rac_liftSelector:@selector(receiveSignalValuesWithR1:r2:r3:) withSignalsFromArray:@[signalA,signalB,signalC]];
[signalA sendNext:@(1)];
[signalB sendNext:@(2)];
[signalC sendNext:@(3)];
}
- (void)receiveSignalValuesWithR1:(id)data1 r2:(id)data2 r3:(id)data3 {
NSLog(@"r1:%@ r2:%@ r3:%@",data1,data2,data3);
}

二、信号过滤
(1)信号过滤_skip
/// 【信号过滤】- 1
/// 跳过前面N次信号
- (void)skip {
RACSubject *signal = [RACSubject subject];
/// 跳过第一次的信号
[[signal skip:1] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[signal sendNext:@(1)];
[signal sendNext:@(2)];
[signal sendNext:@(3)];
[signal sendNext:@(4)];
}

(2)信号过滤_take
/// 【信号过滤】- 2
/// 只执行前面N次信号,此后的都不执行
/// 与skip相反
- (void)take {
RACSubject *signal = [RACSubject subject];
/// 只执行第一次的信号
[[signal take:1] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[signal sendNext:@(1)];
[signal sendNext:@(2)];
[signal sendNext:@(3)];
[signal sendNext:@(4)];
}

(3)信号过滤_ takeLast
/// 【信号过滤】- 3
/// 执行最后N次的信号,前提是订阅者必须调用sendCompleted,这样才能知道总共有多少个信号
- (void)takeLast {
RACSubject *signal = [RACSubject subject];
/// 只执行最后一次的信号
[[signal takeLast:1] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[signal sendNext:@(1)];
[signal sendNext:@(2)];
[signal sendNext:@(3)];
[signal sendNext:@(4)];
[signal sendCompleted];
}

(4)信号过滤_ takeUntil
/// 【信号过滤】- 4
/// 直到某个信号被触发,不再监听
- (void)takeUntil {
RACSubject *signalA = [RACSubject subject];
RACSubject *signalB = [RACSubject subject];
/// 如果signalB信号触发了,那么signalA将不再执行
[[signalA takeUntil:signalB] subscribeNext:^(id _Nullable x) {
NSLog(@"signal A 执行了");
}];
[signalA sendNext:nil];
[signalB sendNext:nil];
[signalA sendNext:nil];
}

(5)信号过滤_ ignore
/// 【信号过滤】- 5
/// 忽略信号,忽略掉规定的值
- (void)ignore {
RACSubject *signal = [RACSubject subject];
/// 忽略@(3)这个值
[[signal ignore:@(3)] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[signal sendNext:@(1)];
[signal sendNext:@(2)];
[signal sendNext:@(3)];
[signal sendNext:@(4)];
}

(6)信号过滤_ filter
/// 【信号过滤】- 6
/// 过滤信号,只返回满足条件的信号
- (void)filter {
RACSubject *signal = [RACSubject subject];
[[signal filter:^BOOL(NSNumber *value) {
/// 筛选条件
/// 只有满足筛选条件的,返回YES,才会到下面的信号
if (value.intValue > 2) {
return YES;
}else{
return NO;
}
}] subscribeNext:^(id _Nullable x) {
/// 满足筛选条件的信号,会转到这里
NSLog(@"%@",x);
}];;
[signal sendNext:@(1)];
[signal sendNext:@(2)];
[signal sendNext:@(3)];
[signal sendNext:@(4)];
}

(7)信号过滤_ distinctUntilChanged
/// 【信号过滤】- 7
/// 监听信号内容的变化,只有发生变化才会触发
/// 在UI控件刷新用的比较多
- (void)distinctUntilChanged {
RACSubject *signal = [RACSubject subject];
[[signal distinctUntilChanged] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[signal sendNext:@(1)];
[signal sendNext:@(2)];
[signal sendNext:@(3)];
[signal sendNext:@(3)]; /// 与上一个信号内容相同,因此被忽略了
[signal sendNext:@(4)];
[signal sendNext:@(3)];
}

三、信号映射
信号映射_map
/// 【信号映射
/// 把源信号的值映射成一个新的值
- (void)map {
RACSubject *signal = [RACSubject subject];
RACSignal *mapSignal = [signal map:^id _Nullable(id _Nullable value) {
return [NSString stringWithFormat:@"处理【%@】",value];
}];
[mapSignal subscribeNext:^(id _Nullable x) {
NSLog(@"最终接受到的值:%@",x);
}];
[signal sendNext:@"源信号"];
}

四、定时器
(1)定时器_delay
/// 【定时器】- 1
/// 延迟多少秒执行
- (void)delay {
RACSubject *signal = [RACSubject subject];
[[signal delay:2] subscribeNext:^(id _Nullable x) {
NSLog(@"延迟2秒执行");
}];
NSLog(@"开始发送信号");
[signal sendNext:nil];
}

(2)定时器_afterDelay
/// 【定时器】- 2
/// 延迟多少秒执行
- (void)afterDelay {
NSLog(@"开始");
[[RACScheduler mainThreadScheduler] afterDelay:2 schedule:^{
NSLog(@"%@",[NSThread currentThread]);
}];
}

(3)定时器_delay
/// 【定时器】- 3
/// 间隔多少秒,循环执行
- (void)interval {
/// 备注:
/// 最好添加一个定时器结束的事件,比如viewcontroller销毁信号,
/// 这样定时器就不会在界面销毁了还在一直执行
[[[RACSignal interval:1 onScheduler:[RACScheduler scheduler]] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(NSDate * _Nullable x) {
NSLog(@"每秒执行一次");
}];
}

五、重试
/// 只要失败,就会重新执行创建信号中的block,直到成功
- (void)retry {
RACSignal *retrySignal = [[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
static int a = 1;
if (a > 3) {
[subscriber sendNext:@(a)];
}else{
[subscriber sendError:nil];
}
a++;
return nil;
}] retry];
[retrySignal subscribeNext:^(id _Nullable x) {
NSLog(@"最终结果:%@",x);
}];
}

六、重放
/// 当一个信号被多次订阅,反复播放内容
- (void)replay {
__block int a = 10;
RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
a += 5;
[subscriber sendNext:@(a)];
return nil;
}]replay];
[signal subscribeNext:^(id x) {
NSLog(@"第一个订阅者%@",x);
}];
[signal subscribeNext:^(id x) {
NSLog(@"第二个订阅者%@",x);
}];
[signal subscribeNext:^(id x) {
NSLog(@"第三个订阅者%@",x);
}];
}

七、执行顺序
/// doNext 、doComplete、doError
- (void)order {
RACSignal *signal = [[[[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"我被订阅了");
[subscriber sendNext:@"0"];
[subscriber sendCompleted];
return nil;
}]doNext:^(id _Nullable x) {
/// 在sendNext:前执行
NSLog(@"doNext:");
}]doCompleted:^{
/// 在sendCompleted:前执行
NSLog(@"doComplete:");
}]doError:^(NSError * _Nonnull error) {
/// 在sendError:前执行
NSLog(@"doError:");
}];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
}

八、节流
/// 某个时间内只获取最后一次的信号
- (void)throttle {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(0,200, self.view.frame.size.width, 300);
btn.backgroundColor = UIColor.grayColor;
[self.view addSubview:btn];
/// 可以避免按钮多次点击误触发事件
/// 0.5 是指从连续点击的最后一次点击开始计算,0.5秒触发点击事件,
/// 如果0.5秒内还有点击,则从最后一次开始重新计时
[[[btn rac_signalForControlEvents:UIControlEventTouchUpInside] throttle:0.5] subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"%@",x);
}];
}
完整DEMO
链接: https://pan.baidu.com/s/15zyu0_daautlYjaCg6lwJA 密码: h14n
网友评论