iOS RAC - RACSignal

作者: Codepgq | 来源:发表于2017-07-12 22:30 被阅读1866次

文章系列
《RACSignal 》
《RACDisposable》
《RACSubject、RACReplaySubject》
《iOS RAC - 基本用法》
《iOS RAC - 定时器》
《iOS RAC - RACMulticastConnection》
《iOS RAC - RACCommand》
《iOS RAC - 核心方法bind》
《iOS RAC - 集合RACTuple、RACSequence》
《iOS RAC - rac_leftSelector》
《iOS RAC - 映射》
《iOS RAC - 过滤》
《iOS RAC - 登录页面,MVVM》

  • 项目中如果没有使用swift的话使用cocoapods 导入pod ‘ReactiveObjC’, ‘~> 3.0.0’ 然后在导入头文件ReactiveObjC.h 就可以使用了,3.0.0以上的版本支持了swift,如果你是纯OC工程,不建议使用3.0.0以上的版本。

RACSignal:顾名思义,信号类,signal本身不具备发送信号的能力,下面通过代码来看看。

在创建RACSignal中先说一下RAC的三部曲

  • 1 创建信号
  • 2 订阅信号
  • 3 发送信息
 //1、创建信号量
    RACSignal * signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        NSLog(@"创建信号量");
        
        //3、发布信息
        [subscriber sendNext:@"I'm send next data"];
        
        NSLog(@"那我啥时候运行");
        
        return nil;
    }];
    
    //2、订阅信号量
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];



代码分析 - 创建信号

[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        return nil;
    }];

这里要创建一个Signal对象,然后它马上给我一个block,
并且在block中要返回一个RACDisposable对象,
刚开始接触RAC的我哪里知道这个是什么鬼,直接返回nil
至此我们完成了第一步,创建信号

然后其内部实现我们并不了解,于是我们点击进去看看其内部如何实现的。

+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
    return [RACDynamicSignal createSignal:didSubscribe];
}

可以看到其内部创建了一个RACDynamicSignal信号,并且把didSubscribe 这个block也传过去了,然后在点进去看看

+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
    RACDynamicSignal *signal = [[self alloc] init];
    signal->_didSubscribe = [didSubscribe copy];
    return [signal setNameWithFormat:@"+createSignal:"];
}

这段代码意思就很清楚了,创建一个RACDynamicSignal,保存didSubscribe这个block,返回RACDynamicSignal这个对象。

通过上面的了解,我们可以知道,创建信号这个方法内部会帮我们创建一个RACDynamicSignal并且保存一个didSubscribeblock。

但是这个block什么时候调用呢?

没错就是在我们订阅信号的时候调用



代码分析 - 订阅信号

//2、订阅信号量
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

这里一订阅信号就给我一个block,并且还带一个参数x,并不知道是饿什么东西,就先打印出来。
然后我们点击进去看下内部实现

- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
    NSCParameterAssert(nextBlock != NULL);
    
    RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
    return [self subscribe:o];
}
  • 1、创建一个订阅者
+ (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed {
    RACSubscriber *subscriber = [[self alloc] init];

    subscriber->_next = [next copy];
    subscriber->_error = [error copy];
    subscriber->_completed = [completed copy];

    return subscriber;
}
保存了nextblock
  • 2、 调用subscribe方法
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
    NSCParameterAssert(subscriber != nil);

    RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
    subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];

    //这里判断didSubcribe是否为空
    if (self.didSubscribe != NULL) {
        RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{

         //这里就在调用didSubscribe方法,并且把刚才传入的subscriber调用出去
            RACDisposable *innerDisposable = self.didSubscribe(subscriber);
            [disposable addDisposable:innerDisposable];
        }];

        [disposable addDisposable:schedulingDisposable];
    }
    
    return disposable;
}
在这个方法中会判断是有有didSubscriber,
如果有就调用block并且把传入进来的subscriber作为block的参数调用出去
订阅信号之后就会运行创建信号的block,

这个时候我们再来看下创建信号的方法

 [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        NSLog(@"创建信号量");
        
        //3、发布信息
        [subscriber sendNext:@"I'm send next data"];
        
        NSLog(@"那我啥时候运行");
        
        return nil;
    }];
    
    //2、订阅信号量
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];
它给我们一个subscriber 
而这个sbuscriber就是我们调用订阅信号的方法所创建的subscriber,然后我们要用这个订阅者发送信息
那我们订阅的信号啥时候调用呢?
  • 当我们的订阅者发送消息的时候就会调用。

这个时候我们看下订阅者发送信息的方法内部做了什么

- (void)sendNext:(id)value {
    @synchronized (self) {
        void (^nextBlock)(id) = [self.next copy];
        if (nextBlock == nil) return;

        nextBlock(value);
    }
}

这里的代码很简洁了 主要就是做了一件事,如果nextblock不为空就把传进来传value原封不动的调用出去。 而这个nextblock就是我们在订阅信号的时候创建的那个subscriber所保存的nextblock。

所以RACSignal的处理流程就是

  • 创建信号的block会在订阅信号的时候调用
  • 订阅信号的block会在订阅者发布信息的时候调用

流程图

signal.png

相关文章

  • (一)、iOS RAC - RACSignal

    (一)、iOS RAC - RACSignal (二)、iOS RAC - RACDisposable(三...

  • iOS RAC - RACSignal

    文章系列《RACSignal 》《RACDisposable》《RACSubject、RACReplaySubje...

  • RACSignal介绍

    RACSignal 在RAC中最核心的类RACSignal,搞定这个类就能用ReactiveCocoa了。 RAC...

  • iOS: RAC篇 - RACSignal

    对于最近公司一个项目涉及到了RAC, 再结合着网上其他大佬的文章做一下整理.RAC的简介就不做介绍了, 百度会不会...

  • iOS:RAC之RacSignal

    理解 RAC框架很强大,之前使用的mvc都是通过赋值然后实现页面的刷新,mvc架构对controller层比较重,...

  • RAC的基本使用

    RAC的基本使用 在RAC中,一切都是信号! RACSignal RACSignal实例化一个信号,首先,需要创建...

  • RAC 组合combine

    RAC(_btn,enabled) = [RACSignal combineLatest:@[_accountTe...

  • iOS开发 「RAC」用RAC实现界面有多个请求都完成后再刷新界

    - (RACSignal *)rac_liftSelector:(SEL)selector withSignals...

  • RAC - RACSignal

    信号类,一般表示将来有数据传递,只要有数据改变,信号内部接收到数据们就会马上发出数据。 信号类,只是表示当前数据改...

  • RAC简单介绍

    RAC在iOS的实际开发中确实是一件有力的武器,此文将从以下几方面讲解 RACSignal RACSubject ...

网友评论

本文标题:iOS RAC - RACSignal

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