ReactiveCocoa简单介绍

一 引入 ReactiveCocoa

使用 pod 引入 选择自己需要的版本

pod 'ReactiveCocoa' 
二 使用 ReactiveCocoa

下方会通过一些简单的实例来介绍一下信号量机制和一些常用的方法。

  1. 引入相应的头文件,在工程中引入下方的头文件(建议在Pch文件中引入)就可以使用我们的ReactiveCocoa框架了

    #import <ReactiveCocoa/ReactiveCocoa.h>
    #import <ReactiveCocoa/RACEXTScope.h>
    
  2. Sequence和Map
    Sequence:队列,是ReactiveCocoa中引入的一个类型,它类似于数组,我们可以暂且把Sequence看做绑定信号量的数组吧。在OC中的NSArray可以通过rac_sequence方法转换成ReactiveCocoa中的Sequence,然后就可以调用处理信号的一些方法了。
    参考以下实例代码:
    a. 把NSArray通过rac_sequence方法生成RAC中的Sequence
    b. 获取该Sequence对象的信号量
    c. 调用Signal的Map方法,使每个元素的首字母大写
    d. 通过subscribNext方法对其进行遍历输出    

    //uppercaseString use map
    - (void)uppercaseString {
    
        RACSequence *sequence = [@[@"you", @"are", @"beautiful"] rac_sequence];
    
        RACSignal *signal =  sequence.signal;
    
        RACSignal *capitalizedSignal = [signal map:^id(NSString * value) {
                                   return [value capitalizedString];
                                }];
    
        [signal subscribeNext:^(NSString * x) {
            NSLog(@"signal --- %@", x);
        }];
    
        [capitalizedSignal subscribeNext:^(NSString * x) {
            NSLog(@"capitalizedSignal --- %@", x);
        }];
    }
    

    下方截图是上个这个方法中的运行结果,从运行结果不难看出,通过Signal相应的方法处理完后,处理的结果会与新返回的信号量所绑定。原信号量中的值保持不变。每次信号量调用相应的方法处理完数据后,都会返回一个新的信号量,而这个信号量是独立于原信号量的。

    reactivelog

    由上面的介绍可知,上面方法中的一坨代码可以写成下方的一串。因为一个方法调用后会返回一个持有新结果的新的信号量,然后在这个信号量的基础上再次调用信号量其他的方法。Signal还有其他一些好用的方法,用法和map方法类似,在此就不一一赘述了,gitHub上有相应的实例文档。

    - (void)uppercaseString {
    
        [[[@[@"you", @"are", @"beautiful"] rac_sequence].signal
         map:^id(NSString * value) {
            return [value capitalizedString];
        }] subscribeNext:^(id x) {
            NSLog(@"capitalizedSignal --- %@", x);
        }];
    }
    
    1. 信号量开关(Switch)

    上面把信号量比喻成水管,那么Switch就是水龙头呢。通过Switch我们可以控制那个信号量起作用,并且可以在信号量之间进行切换。也可以这么理解,把Switch看成另一段水管,Switch对接那个水管,就流那个水管的水,这样比喻应该更为贴切一些。下方是一个关于Switch的一个小实例。

    (1) 首先创建3个自定义信号量(3个水管),前两个水管是用来接通不同的水源的(google, baidu), 而最后一个信号量是用来对接不同水源水管的水管(signalOfSignal)。signalOfSignal接baidu水管上,他就流baidu水源的水,接google水管上就流google水源的水。
    (2) 把signalOfSignal信号量通过switchToLatest方法加工成开关信号量。
    (3) 紧接着是对通过开关数据进行处理。
    (4) 开关对接baidu信号量,然后baidu和google信号量同时往水管里灌入数据,那么起作用的是baidu信号量。
    (5) 开关对接google信号量,google和baidu信号量发送数据,则google信号量输出到signalOfSignal中

    //信号开关Switch
    - (void)signalSwitch {
        //创建3个自定义信号
        RACSubject *google = [RACSubject subject];
        RACSubject *baidu = [RACSubject subject];
        RACSubject *signalOfSignal = [RACSubject subject];
    
        //获取开关信号
        RACSignal *switchSignal = [signalOfSignal switchToLatest];
    
        //对通过开关的信号量进行操作
        [[switchSignal  map:^id(NSString * value) {
            return [@"https//www." stringByAppendingFormat:@"%@", value];
        }] subscribeNext:^(NSString * x) {
            NSLog(@"%@", x);
        }];
    
    
        //通过开关打开baidu
        [signalOfSignal sendNext:baidu];
        [baidu sendNext:@"baidu.com"];
        [google sendNext:@"google.com"];
    
        //通过开关打开google
        [signalOfSignal sendNext:google];
        [baidu sendNext:@"baidu.com/"];
        [google sendNext:@"google.com/"];
    }
    

    上面代码输出结果如下:
    log1

    1. 信号量的合并

    信号量的合并说白了就是把两个水管中的水合成一个水管中的水。但这个合并有个限制,当两个水管中都有水的时候才合并。如果一个水管中有水,另一个水管中没有水,那么有水的水管会等到无水的水管中来水了,在与这个水管中的水按规则进行合并。下面这个实例就是把两个信号量进行合并。

    (1) 首先创建两个自定义的信号量letters和numbers
    (2) 吧两个信号量通过combineLatest函数进行合并,combineLatest说明要合并信号量中最后发送的值
    (3) reduce块中是合并规则:把numbers中的值拼接到letters信号量中的值后边。
    (4) 经过上面的步骤就是创建所需的相关信号量,也就是相当于架好运输的管道。接着我们就可以通过sendNext方法来往信号量中发送值了,也就是往管道中进行灌水。

    //组合信号
    - (void)combiningLatest{
        RACSubject *letters = [RACSubject subject];
        RACSubject *numbers = [RACSubject subject];
    
        [[RACSignal
         combineLatest:@[letters, numbers]
         reduce:^(NSString *letter, NSString *number){
             return [letter stringByAppendingString:number];
         }]
         subscribeNext:^(NSString * x) {
             NSLog(@"%@", x);
         }];
    
        //B1 C1 C2
        [letters sendNext:@"A"];
        [letters sendNext:@"B"];
        [numbers sendNext:@"1"];
        [letters sendNext:@"C"];
        [numbers sendNext:@"2"];
    }
    

    上面示例的运行输出结果如下:
    log2

    1. 信号的合并(merge)

    信号合并就理解起来就比较简单了,merge信号量规则比较简单,就是把多个信号量,放入数组中通过merge函数来合并数组中的所有信号量为一个。类比一下,合并后,无论哪个水管中有水都会在merge产生的水管中流出来的。下方是merge信号量的代码:

    (1) 创建三个自定义信号量, 用于merge
    (2) 合并上面创建的3个信号量
    (3) 往信号里灌入数据

    //合并信号
    - (void)merge {
        RACSubject *letters = [RACSubject subject];
        RACSubject *numbers = [RACSubject subject];
        RACSubject *chinese = [RACSubject subject];
    
        [[RACSignal
         merge:@[letters, numbers, chinese]]
         subscribeNext:^(id x) {
            NSLog(@"merge:%@", x);
        }];
    
        [letters sendNext:@"AAA"];
        [numbers sendNext:@"666"];
        [chinese 
    }
    

    上面代码运行结果如下:
    log3