您的当前位置:首页正文

ReactiveCocoa源码阅读之RACSignal(一)

来源:华拓网

发现要写下来的东西很多,现在就分块记录下来吧。
第一部分先将大头--RACSignal分解。
RACSignal和RACSubscriber的组合其实就是观察者模式,RACSignal是被观察者,而RACSubscriber是观察者。

@protocol RACSubscriber <NSObject>
@required
- (void)sendNext:(id)value;
- (void)sendError:(NSError *)error;
- (void)sendCompleted;
@end

然而RACSubscriber并没有被定义为简单的类,而是被定义成为了protocol,即说明其它任何类只要实现了RACSubscriber的协议,那么它也是观察者,而且具有观察者的行为。
在RACSignal中,隐藏了RACSubscriber的具体实现,即我们不用显式地生成一个订阅者。

    __block id<RACSubscriber> gSubscriber;
    RACSignal* signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        //side effect
        gSubscriber = subscriber;   //1  在初始化时,被RACSignal保存为_didSubscribe,只要被订阅了,就会响应该block;
        return  nil;
    }];
    [signal subscribeNext:^(id x) {
        //订阅者响应模块           //2   只要接收到sendNext事件,就会响应该block;
    }];
    [gSubscriber sendNext:nil]; //3

1、在RACSignal内部,当createSignal时,会首先生成一个RACSignal的子类RACDynamicSignal,并保存该block到子类中的_didSubscribe,然后返回;

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

2、当调用subscribeNext时,即源信号被订阅了,此时就会调用RACSignal子类相对应的subscribe方法。同时将subscribeNext的参数block保存为RACSignal内部subscriber的nextBlock。

- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
    RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
    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;
}

3、而在RACDynamicSignal中,其相对应的subscribe方法便是调用之前保存好的_didSubscribe。

- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
[RACScheduler.subscriptionScheduler schedule:^{
            RACDisposable *innerDisposable = self.didSubscribe(subscriber);
        }];
}

4、当接收到sendNext事件时,就会触发RACSignal内部subscriber的nextBlock。

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

整个过程看起来很绕,其实总结起来就两句话:

  • 当RACSignal被订阅了,就会触发didSubscribe的block;
  • 当发生sendNext事件时,就会触发nextBlock;