RAC学习(一)RACSignal & RACDisposable & RACSubject

一、RAC是什么?

RAC--ReactiveCocoa(RAC) 是GitHub一个开源框架!
RAC--函数响应式编程框架!

二、RAC有什么用?

帮助我们更简单的处理事件

三、引入RAC OC版本

pod 'ReactiveObjC','3.0.0'

四、详解

1、RACSignal:信号类

  1. 创建RACSignal创建一个信号!!(默认是冷信号)
  2. 通过订阅者订阅这个信号!(变成热信号)
  3. 发送信号!
分部代码

第一步:利用RACSignal创建一个冷信号
+ (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe;
在这个类方法中, 有一个参数didSubscribe, 这是一个block, 这个block是一个参数为id类型, 遵守RACSubscriber协议的对象, 返回值为RACDisposable ****类型的block***.

  //1、创建信号 目前是冷信号
    //didSubscribe调用:只要一个信号被订阅就会被调用
    //didSubscribe作用: 利用subscriber发送数据
    RACSignal * signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        NSLog(@"signal has been created");
        //***必须得有返回值***
        return nil;
    }];

代码写到这里, 这个block中的代码会执行吗? 显然不会, 那么, 这段代码什么时候执行呢?

第二步:这时候就需要订阅信号,由冷信号->热信号
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock;
这段代码中, 又有一个block参数, 这个block是一个参数为id类型的对象, 返回值为空的block, 信号订阅时, 我在这个block中什么也不做, 上面的打印同样能够执行:

  //2、订阅信号 将第一步的冷信号 变为 热信号
    //nextBlock调用:只要订阅者发送信息就会调用
    //nextBlock作用:处理数据,展示UI界面
    [signal subscribeNext:^(id x) {
        //x : 信号发送的内容
        NSLog(@"AAA = %@",x);
    }];

第三步:发送信号
- (void)sendNext:(id)value;

//1、创建信号
    //didSubscribe调用:只要一个信号被订阅就会被调用
    //didSubscribe作用: 利用subscriber发送数据
    RACSignal * signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        
        //3、发送信号 subscriber
        [subscriber sendNext:@"发送信号"];
        
        //有返回值
        return nil;
    }];

底层实现

我们来看一下这个内部是怎么实现的
第一步:创建信号


RACSignal_createSignal.png

RACDynamicSignal_createSignal.png

其中signal->_didSubscribe = [didSubscribe copy];这句代码将didSubscribe这个block保存在对象的属性中.

第二步:订阅信号

RACSignal_subscribeNext.png

上面这个函数就是创建了一个RACSubscriber对象,然后被调用进入真正的订阅函数。

根据创建信号的底层方法,可以看到信号对象是RACDynamicSignal

信号对象.png

RAC学习(一)RACSignal & RACDisposable & RACSubject_第1张图片
查找对应的函数.png

最终的订阅函数


RAC学习(一)RACSignal & RACDisposable & RACSubject_第2张图片
RACDynamicSignal_subScribe.png

从上图我们可以看到, didSubscribe这个block在信号订阅的时候被调用, 在调用的同时, 把subscriber这个参数传给block, 所以我们在

RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {
    NSLog(@"signal has been created");
    [subscriber sendNext:@"subscriber send"];
    return nil;
}];

这个代码块内部是可以拿到subscriber这个对象的, 然后我再调用sendNext这个方法, 会出现什么情况呢?

第三步:发送信号

RAC学习(一)RACSignal & RACDisposable & RACSubject_第3张图片
RACSubscriber_sendNext.png

根据创建订阅信号的函数,可以找到


创建订阅者.png
RAC学习(一)RACSignal & RACDisposable & RACSubject_第4张图片
进一步观察.png

可以看到这一个函数中,将block进行了属性的保存。

RAC学习(一)RACSignal & RACDisposable & RACSubject_第5张图片
block调用.png
RAC学习(一)RACSignal & RACDisposable & RACSubject_第6张图片
运行.png

2、RACDisposable :取消订阅类

看到createSignalblock是有返回值的RACDisposable

RACSignal * signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
        RACDisposable * disposible = [RACDisposable disposableWithBlock:^{
            NSLog(@"disposible");
        }];
        //有返回值
        return disposible;
    }];

运行如下图


RAC学习(一)RACSignal & RACDisposable & RACSubject_第7张图片
运行.png

可以看到的是: 这个返回值是RACDisposable类型的, 然后我们创建一个RACDisposable对象是用+ (instancetype)disposableWithBlock:(void (^)(void))block这个类方法, 同样参数也是一个block, 但是这个block很快就被调用了, 这是为什么呢?

RAC学习(一)RACSignal & RACDisposable & RACSubject_第8张图片
subScriber生命周期.png

subscribeNext:方法调用时, 赋值给了subscriberdisposable属性(可以先这么理解), 当subscriber生存周期结束时, 就会调

- (void)dealloc {
    [self.disposable dispose];
}

所以这个时候

RACDisposable *disposable = [RACDisposable disposableWithBlock:^{
      NSLog(@"disposable");
}];
return disposable;

这段代码中的打印就会执行了.

但当subscriber被强引用时, dealloc方法不被调用, disposable也不会被调用.

RAC学习(一)RACSignal & RACDisposable & RACSubject_第9张图片
强引用```subscriber```时, ```disposable```不会被调用.png

如果subscriber被强引用时, 我又想取消订阅, 应该怎么做呢?
subscribeNext:这个方法是有返回值的, 这个返回值其实就是上面
didSubscribeblock的返回值(可以先这么理解)
我用一个变量接收一样, 然后手动disposable即可:

RAC学习(一)RACSignal & RACDisposable & RACSubject_第10张图片
手动操作.png

那么RACDisposable是做什么用的呢?

这个类可以帮助我们取消订阅, 当信号发送完毕了或者失败了之后取消订阅, 并调用指定的代码.

3、RACSubject类

在RAC中, 还有一个类非常重要, 也很特殊, 叫做RACSubject, 这个类即可以创建信号, 也可以发送信号. 代码如下:

RACSubject *subject = [RACSubject subject];
[subject subscribeNext:^(id  _Nullable x) {
    NSLog(@"subject has been subscribed %@", x);
}];
[subject sendNext:@"subject has been sended"];
RAC学习(一)RACSignal & RACDisposable & RACSubject_第11张图片
subject发送信号

所以, 用RACSubject的好处就是: 可以订阅多个信号, 最后发送信号的时候一起调用.

RAC学习(一)RACSignal & RACDisposable & RACSubject_第12张图片
测试订阅多个信号

RACSubject的本质其实和RACSignal是一样的, 那为什么它又可以创建信号, 又可以订阅信号呢?

在OC中, 是没有多继承的概念的, 要想实现多继承的效果, 可以先继承一个类, 然后再实现一个或者多个协议, 这样就实现了多继承的效果
继承RACSignal.png

五、RAC实战

那么, 说了这么多, 这个RAC有什么用呢?
用处大了, 因为它可以实现KVO , 代理, 通知, block的功能, 集多种功能于一身, 当你用了RAC之后, 你可以利用RAC实现以上设计模式能实现的功能.

参考网址:http://www.jianshu.com/p/381b29b01457 (学豆)

完!

你可能感兴趣的:(RAC学习(一)RACSignal & RACDisposable & RACSubject)