组合
//把多个信号聚合成你想要的信号
- (void)loadTestData
{
RACSignal *combinSignal = [RACSignal combineLatest:@[self.userName.rac_textSignal,self.password.rac_textSignal] reduce:^id(NSString *account, NSString *pwd){
//reduce里的参数一定要和数组里的元素一一对应起来
//block: 只要源信号发送内容,就会调用,组合成一个新值。
return @(account.length && pwd.length);
}];
RAC(self.loginBtn,enabled) = combinSignal;
}
- (void)zipWith
{
// zipWith:把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,并且把两个信号的内容合并成一个元祖,才会触发压缩流的next事件
// 创建信号A
RACSubject *signalA = [RACSubject subject];
// 创建信号B
RACSubject *signalB = [RACSubject subject];
// 压缩成一个信号
// **-zipWith-** :当一个界面多个请求的时候,要等所有的请求完成才更新UI
RACSignal *zipSignal = [signalA zipWith:signalB];
[zipSignal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);//所有的值将会被包装成元祖
}];
//发送信号 交互顺序,元祖内的元素的顺序是不会变的,跟发送的顺序无关,而是跟压缩的顺序有关
[signalA sendNext:@(1)];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[signalB sendNext:@(2)];
});
}
/// 任何一个信号请求完成都会被订阅到
/// merge: 多个信号合并成一个信号,任何一个信号有新值都会调用
- (void)merge {
// 创建信号A
RACSubject *signalA = [RACSubject subject];
// 创建信号B
RACSubject *signalB = [RACSubject subject];
// 合并信号
RACSignal *merge = [signalA merge:signalB];
//订阅信号
[merge subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 发送信号
[signalB sendNext:@"下部分更新"];
[signalA sendNext:@"上部分更新"];
/**
2020-06-01 15:28:07.725 RACUserful[9883:197270] 下部分更新
2020-06-01 15:28:07.726 RACUserful[9883:197270] 上部分更新
*/
}
/// then -- 使用需求:有两部分数据:想让上部分先进行网络请求但是过滤掉数据,然后进行下部分的,拿到部分数据
- (void)then {
RACSignal *signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
NSLog(@"--------发送上部分请求---------afn");
[subscriber sendNext:@"上部分数据"];
[subscriber sendCompleted];//必须调用sendCompleted方法
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
NSLog(@"--------发送下部分请求---------afn");
[subscriber sendNext:@"下部分数据"];
return nil;
}];
//then将会忽略掉第一个信号的所有值
//注意 第一个信号必须要调用 sendComplented
RACSignal *thenSignal = [signalA then:^RACSignal * _Nonnull{
return signalB;
}];
[thenSignal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
/**
2020-06-01 15:44:32.806 RACUserful[9883:197270] --------发送上部分请求---------afn
2020-06-01 15:44:32.806 RACUserful[9883:197270] --------发送下部分请求---------afn
2020-06-01 15:44:32.806 RACUserful[9883:197270] 下部分数据
*/
}
/// concat --- 使用需求:有两部分数据,想让上部分先执行,完了之后再让下部分执行 (都可以获得值)
- (void)concat {
RACSignal *signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
NSLog(@"--------发送上部分请求---------afn");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"上部分数据1"];//必须调用sendCompleted方法
[subscriber sendCompleted];
});
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
NSLog(@"--------发送下部分请求---------afn");
[subscriber sendNext:@"下部分数据"];
return nil;
}];
//then将会忽略掉第一个信号的所有值
//注意 第一个信号必须要调用 sendComplented
RACSignal *concatSignal = [signalA concat:signalB];
[concatSignal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
/**
2020-06-01 15:53:02.208 RACUserful[9883:197270] --------发送上部分请求---------afn
2020-06-01 15:53:02.208 RACUserful[9883:197270] 上部分数据
2020-06-01 15:53:02.209 RACUserful[9883:197270] --------发送下部分请求---------afn
2020-06-01 15:53:02.209 RACUserful[9883:197270] 下部分数据
*/
}
过滤
/// 跳跃:skip传入2 跳过前面两个值
/// 实际用途:在实际开发中,后台返回的数据前几个没用,想跳过就直接skip
- (void)skip {
//1.
RACSubject *subject = [RACSubject subject];
[[subject skip:2] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[subject sendNext:@1];
[subject sendNext:@2];
[subject sendNext:@3];
//2.
RACSignal *singal = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
[subscriber sendNext:@4];
[subscriber sendNext:@5];
[subscriber sendNext:@6];
return nil;
}];
[[singal skip:1] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
/**
2020-06-01 11:08:04.294 RACUserful[4450:86732] 3
2020-06-01 11:08:04.295 RACUserful[4450:86732] 5
2020-06-01 11:08:04.295 RACUserful[4450:86732] 6
*/
}
/// distinctUntilChanged : -如果当前的值跟上一次的值一样,就不会被订阅到,很实用
- (void)distinctUntilChanged {
RACSubject *subject = [RACSubject subject];
[[subject distinctUntilChanged] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[subject sendNext:@{
@"title":@"name",
@"vale":@"1"
}];
[subject sendNext:@{
@"title":@"name",
@"vale":@"2"
}];
[subject sendNext:@{
@"title":@"name",
@"vale":@"2"
}];
[subject sendNext:@3];
/**
2020-06-01 11:14:36.511 RACUserful[4450:86732] {
title = name;
vale = 1;
}
2020-06-01 11:14:36.511 RACUserful[4450:86732] {
title = name;
vale = 2;
}
2020-06-01 11:14:36.511 RACUserful[4450:86732] 3
*/
}
/// take: 可以屏蔽一些值,去前面几个值
- (void)take {
RACSubject *sub = [RACSubject subject];
[[sub take:2] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[sub sendNext:@1];
[sub sendNext:@2];
[sub sendNext:@3];
/**
2020-06-01 11:24:55.845053+0800 RACUserful[5331:99724] 1
2020-06-01 11:24:55.845256+0800 RACUserful[5331:99724] 2
*/
}
/// 这里的takeLast 和 take一样,也是截取,不过是倒序,从最后开始数
/// 注意这里的takeLast 使用时必须调用 complented ,这样才能确定最后值
- (void)takeLast
{
RACSubject *sub = [RACSubject subject];
[[sub takeLast:2] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[sub sendNext:@1];
[sub sendNext:@2];
[sub sendNext:@3];
[sub sendCompleted];
/**
2020-06-01 11:27:01.145 RACUserful[5331:99724] 2
2020-06-01 11:27:01.146 RACUserful[5331:99724] 3
*/
}
/// takeUntil : 给 takeUntil 传递的是哪个信号,那么当这个信号发送信号或者sendComplented,就不能再接受源信号的内容了
- (void)takeUntil {
RACSubject *sub1 = [RACSubject subject];
RACSubject *sub2 = [RACSubject subject];
[[sub1 takeUntil:sub2] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//注意:谁takeUntil谁终止,并不会影响作为条件的sub2
/**
[sub2 subscribeNext:^(id _Nullable x) {
NSLog(@"sub2---%@",x);
}];
*/
[sub1 sendNext:@"1"];
[sub2 sendNext:@"2"];
[sub1 sendNext:@"3"];
/**
2020-06-01 11:30:38.926 RACUserful[5331:99724] 1
*/
}
///忽略掉一些值
- (void)ignore {
// ignore:忽略一些值
// ignoreValues:表示忽略所有的值
// 1.创建信号
RACSubject *subject = [RACSubject subject];
// 2. 忽略一些值
RACSignal *ignoreSignal = [subject ignore:@2];
// 3. 订阅信号
[ignoreSignal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[subject sendNext:@2];
}
映射
//遍历绑定
- (void)loadTestData
{
//创建信号
RACSubject *subject = [RACSubject subject];
//绑定信号
RACSignal *bindSingal = [subject map:^id _Nullable(id _Nullable value) {
//返回的类型就是你需要映射的值
return [NSString stringWithFormat:@"ws:%@",value];//这里将源信号发送给123,前面拼接ws
}];
//订阅绑定信号
[bindSingal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//发送信号
[subject sendNext:@"123"];
}
- (void)filterMap {
//创建信号
RACSubject *subject = [RACSubject subject];
//绑定信号
RACSignal *bindSingal = [subject flattenMap:^__kindof RACSignal * _Nullable(id _Nullable value) {
//block:只要源信号发送内容就会调用
//value:就是源信号发送的内容
//返回信号用于包装成修改内容的值
return [RACReturnSignal return:@([value intValue]+2)];
}];
//订阅绑定信号
//flattenMap中返回的是什么信号,订阅的就是什么信号(那么,x的值等于value的值,如果我们操作value的值,x也会随之改变)
[bindSingal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
//发送信号
[subject sendNext:@"123"];
}
- (void)filterMap2{
// flattenMap 主要用于信号中的信号
// 创建信号
RACSubject *signalofSignals = [RACSubject subject];
RACSubject *signal = [RACSubject subject];
//订阅信号,这里之前用sendNext和 switchToLatest 的方式,这次不再使用老方法
//方法一
// RACSignal *bindSignal = [signalofSignals flattenMap:^__kindof RACSignal * _Nullable(id _Nullable value) {
// return value;
// }];
// [bindSignal subscribeNext:^(id _Nullable x) {
// NSLog(@"%@",x);
// }];
//方法二----开发中常用的 ,就是合并方法一
[[signalofSignals flattenMap:^__kindof RACSignal * _Nullable(id _Nullable value) {
return value;
}] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[signalofSignals sendNext:signal];
[signal sendNext:@"456"];
}
RACCommand的用法
/// 普通做法
- (void)loadTestData1
{
//不能返回空的信号
//1.创建命令
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
// block调用,执行命令的时候传进来的参数
NSLog(@"%@",input);
//返回值不允许为nil
return [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
//模拟数据
[subscriber sendNext:@"执行命令所产生的数据"];
return nil;
}];
}];
//执行命令
RACSignal *signal = [command execute:@2];// 这里其实用到的是replaySubject 可以先发送命令再订阅,大致原理如此
//如何拿到执行命令后产生的数据
//1.订阅执行命令返回的信号
//订阅信号
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
/**
2020-06-01 09:51:46.519 RACUserful[2079:44351] 2
2020-06-01 09:51:46.529 RACUserful[2079:44351] 执行命令所产生的数据
*/
}
/// 一般做法
- (void)loadTestData2
{
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
//执行订阅,这里的input为传递进来的参数
NSLog(@"%@",input);
return [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
NSLog(@"执行命令所产生的数据");
[subscriber sendNext:@1];
return nil;
}];
}];
//方式二:
//订阅信号,这里的必须先订阅才能发送命令
//executionSignals代表信号源,信号中信号
[command.executionSignals subscribeNext:^(RACSignal *x) {
NSLog(@"%@",x);
[x subscribeNext:^(id _Nullable y) {
NSLog(@"%@",y);
}];
}];
[command execute:@2];
/**
2020-06-01 09:52:55.595 RACUserful[2079:44351] 2
2020-06-01 09:52:55.604 RACUserful[2079:44351] name:
2020-06-01 09:52:55.604 RACUserful[2079:44351] 执行命令所产生的数据
2020-06-01 09:52:55.604 RACUserful[2079:44351] 1
*/
}
- (void)loadTestData3
{
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
//执行订阅,这里的input为传递进来的参数
NSLog(@"%@",input);
return [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
[subscriber sendNext:@"执行命令所产生的数据"];
return nil;
}];
}];
// 方式三
// switchToLatest获取最新发送的信号,只能用于信号中信号。
[command.executionSignals.switchToLatest subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[command execute:@3];
/**
2020-06-01 09:50:03.527968+0800 RACUserful[2079:44351] 3
2020-06-01 09:50:03.555969+0800 RACUserful[2079:44351] 执行命令所产生的数据
*/
}
/// 监听事件有没有完成
- (void)loadTestData5
{
//注意:当前命令内部发送数据完成,一定要主动发送完成
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
//执行订阅,这里的input为传递进来的参数
NSLog(@"%@",input);
return [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
[subscriber sendNext:@"执行命令所产生的数据"];
// 发送完成
[subscriber sendCompleted];
return nil;
}];
}];
// 监听事件是否已经完成
[command.executing subscribeNext:^(NSNumber * _Nullable x) {
if([x boolValue] == YES){
NSLog(@"当前正在执行 %@",x);
}else{
NSLog(@"没有执行或者执行完成");
}
}];
[command execute:@5];
}
这里需要注意的是switchToLatest的使用
///switchToLatest用法
- (void)loadTestData4
{
//创建信号中的信号
RACSubject *singalOfsingals = [RACSubject subject];
RACSubject *singalA = [RACSubject subject];
//switchToLatest 获取信号中信号发送的最新信号
[singalOfsingals.switchToLatest subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
[singalOfsingals sendNext:singalA];
[singalA sendNext:@4];
/**
以上写法等价于
[singalOfsingals subscribeNext:^(id _Nullable x) {
[x subscribeNext:^(id _Nullable y) {
NSLog(@"%@",y);
}];
}];
[singalOfsingals sendNext:singalA];
[singalA sendNext:@4];
2020-06-01 09:56:36.470 RACUserful[2079:44351] 4
*/
}
以上是比较简单的语法糖,适用常见的一些场景。