美文网首页
RAC信号和订阅

RAC信号和订阅

作者: 高思阳 | 来源:发表于2019-05-15 11:37 被阅读0次

    RAC中创建一个新的信号的方法:

    //代码段(1)
    RACSignal *newSignal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            [subscriber sendNext:@(1)];
            return nil;
    }];
    

    点进去,可以查看RACSignal里面createSignal:方法的实现,是直接调用的RACDynamicSignalcreateSignal: 方法,RACDynamicSignal是一个继承自RACSignal的类。

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

    根据代码段(2),我们可以修改代码段(1),如下:

    //代码段(3)
    //didSubscribe这个block就是代码段(1)后面展开的block
    RACDisposable * (^didSubscribe)(id<RACSubscriber> subscriber) = ^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            [subscriber sendNext:@(1)];
            return nil;
    };
    
    //[RACSignal createSignal:didSubscribe]; 内部直接 return [RACDynamicSignal createSignal:didSubscribe];
    RACSignal *newSignal =  [RACDynamicSignal createSignal:didSubscribe]; 
    

    查看RACDynamicSignal类中createSignal:方法的实现:

    //代码段(4)
    @interface RACDynamicSignal ()
    @property (nonatomic, copy, readonly) RACDisposable * (^didSubscribe)(id<RACSubscriber> subscriber);
    @end
    
    + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
        RACDynamicSignal *signal = [[self alloc] init];
        signal->_didSubscribe = [didSubscribe copy];
        return [signal setNameWithFormat:@"+createSignal:"];
    }
    

    代码段(4)就是创建了一个RACDynamicSignal对象,并且把didSubscribe这个block,赋值给该对象属性didSubscribe对应的实例变量_didSubscribe,然后给该对象设置name属性为@"+createSignal:"

    这里我们再重新指出:RACDynamicSignal继承自RACSignal,RACSignal继承自RACStream。

    根据代码段(4),我们可以修改代码段(3),如下:

    代码段(5)
    RACDisposable * (^didSubscribe)(id<RACSubscriber> subscriber) = ^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            [subscriber sendNext:@(1)];
            return nil;
    };
    
    //RACDynamicSignal继承自RACSignal
    RACSignal *newSignal =  [[RACDynamicSignal alloc]init]; 
    newSignal->_didSubscribe = didSubscribe;
    
    //setNameWithFormat:方法是RACStream中的方法,而RACSignal继承自RACStream
    [newSignal setNameWithFormat:@"+createSignal:"];
    

    这里将子类RACDynamicSignal赋值给父类RACSignal。需要说明一点:继承是将父类的方法与属性继承给了子类,所以子类不用重复声明。同时子类也能声明自己的方法与属性。这些子类声明的方法与属性是父类没有的。所以可以通过子类给父类赋值,因为父类有的子类都有。不能通过父类给子类赋值,因为子类自己独有的方法与属性父类没有,当通过父类去访问子类独有的方法和属性的时候就会报错。

    到此,信号的创建已经看完了。接下来看看信号的订阅。

    信号订阅的方法如下:

    代码段(6)
    [newSignal subscribeNext:^(id  _Nullable x) {
            NSLog(@"%@",x);
    }];
    

    把代码段(6)改一下:

    代码段(7)
    void (^nextBlock)(id x) = ^(id  _Nullable x) {
            NSLog(@"%@",x);
    };
    
    [newSignal subscribeNext:nextBlock];
    

    点进subscribeNext:方法:

    - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
        NSCParameterAssert(nextBlock != NULL);
        
        RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
    
        //这里调用的是RACDynamicSignal的subscribe:方法,因为代码段(5)中,RACSignal *newSignal =  [[RACDynamicSignal alloc]init]; 
        //把RACSignal对象赋值为其子类RACDynamicSignal对象,所以调用的就是它的子类对象的方法,而不是自己内部的方法。
        return [self subscribe:o];
    }
    
    + (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;
    }
    
    - (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
        NSCParameterAssert(subscriber != nil);
    
        RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
        subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
    
        if (self.didSubscribe != NULL) {
            RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
                RACDisposable *innerDisposable = self.didSubscribe(subscriber);// 调用了`didSubscribe`这个block
                [disposable addDisposable:innerDisposable];
            }];
    
            [disposable addDisposable:schedulingDisposable];
        }
        
        return disposable;
    }
    

    这个方法里面创建了一个RACSubscriber对象,并且在该对象内部保存了三个block到对应的实例变量中,分别是_next_error_completed三个block变量,我们这里_next保存了代码段(7)的nextBlock,而剩下两个实例变量只是保存了NULL。
    我们可以看到- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber方法中第六行(已标注,对应代码 self.didSubscribe(subscriber)),调用了didSubscribe这个block。

    综上,信号被订阅(调用subscribeNext:方法)的时候,didSubscribe这个block被调用,也就是newSignal中的_didSubscribe(对应的就是代码段(2)的didSubscribe)这个block被调用。

    接下来看看

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

    这里调用了上面RACSubscriber对象_next实例变量的nextBlock(代码段(7)的nextBlock),此时就相当于订阅者收到了消息。

    总结:

    + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe //①
    - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock //②
    - (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber //③
    - (void)sendNext:(id)value //④
    

    使用 方法① 创建信号RACSignal对象的时候,实际内部创建了一个子类对象RACDynamicSignal,在这个子类对象中保存了 方法① 后面的didSubscribe(block块),然后将这个对象返回。

    使用 方法② 订阅信号RACSignal对象的时候,内部生成一个subscriber(订阅者对象RACSubscriber对象)。这个订阅者对象用实例变量_next保存了传进来的参数nextBlock(类似方法还会保存一个errorBlock和一个completedBlock)。并且信号RACSignal对象(实际保存的是子类对象RACDynamicSignal)调用 方法③方法③ 内部调用了 方法① 中被保存的 didSubscribe(block块),并且把订阅者对象当做block的参数传了过去。

    方法① 中使用上面通过didSubscribe(block块)传进来的subscriber(订阅者对象)调用 方法④方法④ 内部调用了subscriber(订阅者对象)里面保存的那个nextBlock(上面_next中保存的block)。

    相关文章

      网友评论

          本文标题:RAC信号和订阅

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