美文网首页iOS精选
RAC学习(一)RACSignal & RACDispo

RAC学习(一)RACSignal & RACDispo

作者: lionsom_lin | 来源:发表于2017-04-18 20:52 被阅读119次

    一、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<RACSubscriber> subscriber))didSubscribe;
    在这个类方法中, 有一个参数didSubscribe, 这是一个block, 这个block是一个参数为id类型, 遵守RACSubscriber协议的对象, 返回值为RACDisposable ****类型的block***.

      //1、创建信号 目前是冷信号
        //didSubscribe调用:只要一个信号被订阅就会被调用
        //didSubscribe作用: 利用subscriber发送数据
        RACSignal * signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> 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<RACSubscriber> 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 查找对应的函数.png

    最终的订阅函数


    RACDynamicSignal_subScribe.png

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

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

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

    第三步:发送信号

    RACSubscriber_sendNext.png

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


    创建订阅者.png 进一步观察.png

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

    block调用.png 运行.png

    2、RACDisposable :取消订阅类

    看到createSignalblock是有返回值的RACDisposable

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

    运行如下图


    运行.png

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

    subScriber生命周期.png

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

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

    所以这个时候

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

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

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

    强引用```subscriber```时, ```disposable```不会被调用.png

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

    手动操作.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"];
    
    subject发送信号

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

    测试订阅多个信号

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

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

    五、RAC实战

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

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

    完!

    相关文章

      网友评论

        本文标题:RAC学习(一)RACSignal & RACDispo

        本文链接:https://www.haomeiwen.com/subject/fipqzttx.html