一直想写篇关于RAC的文章,一是分享二是做为笔记,由于项目忙先简单的贴一个自己当初学习的时候代码吧
一、RACCommand
// RACCommand 的使用: 使用场景,监听按钮点击,网络请求 - (void)RACCommand{ // 1.创建命令 RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) { NSLog(@"执行命令"); // 创建空信号,必须返回信号 // return [RACSignal empty]; // 2.创建信号,用来传递数据 return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@"请求数据"]; // 注意:数据传递完,最好调用sendCompleted,这时命令才执行完毕。 [subscriber sendCompleted]; return nil; }]; }]; // 强引用命令,不要被销毁,否则接收不到数据 self.conmmand = command; // 3.订阅RACCommand中的信号 [command.executionSignals subscribeNext:^(id x) { NSLog(@"command.executionSignals %@",x); [x subscribeNext:^(NSString *x) { NSLog(@"x subscribeNext %@",x); }]; }]; // RAC高级用法 // switchToLatest:用于signal of signals,获取signal of signals发出的最新信号,也就是可以直接拿到RACCommand中的信号 // [command.executionSignals.switchToLatest subscribeNext:^(id x) { // // NSLog(@"command.executionSignals.switchToLatest %@",x); // }]; // 4.监听命令是否执行完毕,默认会来一次,可以直接跳过,skip表示跳过第一次信号。 [[command.executing skip:1] subscribeNext:^(id x) { if ([x boolValue] == YES) { // 正在执行 NSLog(@"正在执行"); }else{ // 执行完成 NSLog(@"执行完成"); } }]; // 5.执行命令 [self.conmmand execute:@1]; }
二、RACMulticastConnection
// RACMulticastConnection 使用场景:用于当一个信号,被多次订阅时,为了保证创建信号时,避免多次调用创建信号中的block,造成副作用,可以使用这个类处理 - (void)RACMulticastConnection{ // 需求:假设在一个信号中发送请求,每次订阅一次都会发送请求,这样就会导致多次请求。 // 解决:使用RACMulticastConnection就能解决. // 1.创建请求信号 // RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { // // // NSLog(@"发送请求"); // // return nil; // }]; // // 2.订阅信号 // [signal subscribeNext:^(id x) { // // NSLog(@"接收数据"); // // }]; // // 2.订阅信号 // [signal subscribeNext:^(id x) { // // NSLog(@"接收数据"); // // }]; // // 3.运行结果,会执行两遍发送请求,也就是每次订阅都会发送一次请求 // RACMulticastConnection:解决重复请求问题 // 1.创建信号 RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { NSLog(@"发送请求"); [subscriber sendNext:@1]; return nil; }]; // 2.创建连接 RACMulticastConnection *connect = [signal publish]; // 3.订阅信号, // 注意:订阅信号,也不能激活信号,只是保存订阅者到数组,必须通过连接,当调用连接,就会一次性调用所有订阅者的sendNext: [connect.signal subscribeNext:^(id x) { NSLog(@"订阅者一信号 %@",x); }]; [connect.signal subscribeNext:^(id x) { NSLog(@"订阅者二信号 %@",x); }]; // 4.连接,激活信号 [connect connect]; }
三、bind
// ReactiveCocoa核心方法bind - (void)bind{ // 假设想监听文本框的内容,并且在每次输出结果的时候,都在文本框的内容拼接一段文字“输出:” // 方式一:在返回结果后,拼接。 [self.textField.rac_textSignal subscribeNext:^(id x) { NSLog(@"输出:%@",x); }]; // map [[_textField.rac_textSignal map:^id(id value) { // 当源信号发出,就会调用这个block,修改源信号的内容 // 返回值:就是处理完源信号的内容。 return [NSString stringWithFormat:@"输出:%@",value]; }] subscribeNext:^(id x) { NSLog(@"%@",x); }]; }
四、concat
// 操作方法组合 - (void)concat{ RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@1]; [subscriber sendCompleted]; return nil; }]; RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@2]; return nil; }]; // 把signalA拼接到signalB后,signalA发送完成,signalB才会被激活。 RACSignal *concatSignal = [signalA concat:signalB]; // 以后只需要面对拼接信号开发。 // 订阅拼接的信号,不需要单独订阅signalA,signalB // 内部会自动订阅。 // 注意:第一个信号必须发送完成,第二个信号才会被激活 [concatSignal subscribeNext:^(id x) { NSLog(@"%@",x); }]; // concat底层实现: // 1.当拼接信号被订阅,就会调用拼接信号的didSubscribe // 2.didSubscribe中,会先订阅第一个源信号(signalA) // 3.会执行第一个源信号(signalA)的didSubscribe // 4.第一个源信号(signalA)didSubscribe中发送值,就会调用第一个源信号(signalA)订阅者的nextBlock,通过拼接信号的订阅者把值发送出来. // 5.第一个源信号(signalA)didSubscribe中发送完成,就会调用第一个源信号(signalA)订阅者的completedBlock,订阅第二个源信号(signalB)这时候才激活(signalB)。 // 6.订阅第二个源信号(signalB),执行第二个源信号(signalB)的didSubscribe // 7.第二个源信号(signalA)didSubscribe中发送值,就会通过拼接信号的订阅者把值发送出来. }
五、than
- (void)than{ // then:用于连接两个信号,当第一个信号完成,才会连接then返回的信号 // 注意使用then,之前信号的值会被忽略掉. // 底层实现:1、先过滤掉之前的信号发出的值。2.使用concat连接then返回的信号 [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@1]; [subscriber sendCompleted]; return nil; }] then:^RACSignal *{ return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@2]; return nil; }]; }] subscribeNext:^(id x) { // 只能接收到第二个信号的值,也就是then返回信号的值 NSLog(@"%@",x); }]; }
六、merge
- (void)merge{ // merge:把多个信号合并成一个信号 //创建多个信号 RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@1]; return nil; }]; RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@2]; return nil; }]; // 合并信号,任何一个信号发送数据,都能监听到. RACSignal *mergeSignal = [signalA merge:signalB]; [mergeSignal subscribeNext:^(id x) { NSLog(@"%@",x); }]; // 底层实现: // 1.合并信号被订阅的时候,就会遍历所有信号,并且发出这些信号。 // 2.每发出一个信号,这个信号就会被订阅 // 3.也就是合并信号一被订阅,就会订阅里面所有的信号。 // 4.只要有一个信号被发出就会被监听。 }
七、zipWith
- (void)zipWith{ //zipWith:把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,并且把两个信号的内容合并成一个元组,才会触发压缩流的next事件。 RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@1]; return nil; }]; RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@2]; return nil; }]; // 压缩信号A,信号B RACSignal *zipSignal = [signalA zipWith:signalB]; [zipSignal subscribeNext:^(id x) { NSLog(@"%@",x); }]; // 底层实现: // 1.定义压缩信号,内部就会自动订阅signalA,signalB // 2.每当signalA或者signalB发出信号,就会判断signalA,signalB有没有发出个信号,有就会把最近发出的信号都包装成元组发出。 }
八、combineLatest
// combineLatest:将多个信号合并起来,并且拿到各个信号的最新的值,必须每个合并的signal至少都有过一次sendNext,才会触发合并的信号。 - (void)combineLatest{ RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@1]; return nil; }]; RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@2]; return nil; }]; // 把两个信号组合成一个信号,跟zip一样,没什么区别 RACSignal *combineSignal = [signalA combineLatestWith:signalB]; [combineSignal subscribeNext:^(id x) { NSLog(@"%@",x); }]; // 底层实现: // 1.当组合信号被订阅,内部会自动订阅signalA,signalB,必须两个信号都发出内容,才会被触发。 // 2.并且把两个信号组合成元组发出。 }
九、combineLatestReduce
// 组合并聚合 - (void)combineLatestReduce{ RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@1]; return nil; }]; RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:@2]; return nil; }]; // 聚合 // 常见的用法,(先组合在聚合)。combineLatest:(id<NSFastEnumeration>)signals reduce:(id (^)())reduceBlock // reduce中的block简介: // reduceblcok中的参数,有多少信号组合,reduceblcok就有多少参数,每个参数就是之前信号发出的内容 // reduceblcok的返回值:聚合信号之后的内容。 RACSignal *reduceSignal = [RACSignal combineLatest:@[signalA,signalB] reduce:^id(NSNumber *num1 ,NSNumber *num2){ return [NSString stringWithFormat:@"%@ %@",num1,num2]; }]; [reduceSignal subscribeNext:^(id x) { NSLog(@"%@",x); }]; // 底层实现: // 1.订阅聚合信号,每次有内容发出,就会执行reduceblcok,把信号内容转换成reduceblcok返回的值。 }