RAC源码解析

RAC是一个函数响应编程框架。

先来一个简单的RAC使用:

RACSignal使用步骤:
1.创建信号 + (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe
2.订阅信号,才会激活信号. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
3.发送信号 - (void)sendNext:(id)value

- (void)test_signal
{
    // 1.创建信号
    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
        // 3.发送信号
        NSLog(@"%@:发送信号", NSStringFromSelector(_cmd));
        [subscriber sendNext:@(1)];
        return nil;
    }];
    // 2.订阅信号
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@:x:%@", NSStringFromSelector(_cmd), x);
    }];
}

一个信号的简单使用,就是如上代码所示。
我们也可以把它按照下面的去理解:

- (void)test_signal_detail
{
    // 当订阅信号的时候,需要处理的事情,这里面会发送信号
    RACDisposable *(^doSomethingWhenSubscribeSignal)(id) = ^RACDisposable *(id subscriber) {
        // 3.发送信号
        NSLog(@"%@:发送信号", NSStringFromSelector(_cmd));
        [subscriber sendNext:@(1)];
        return nil;
    };
    
    // 1.创建信号
    RACSignal *signal = [RACSignal createSignal:doSomethingWhenSubscribeSignal];
    // 当收到信号的时候,需要处理的事情
    void (^doSomethingWhenReceiveSignal)(id) = ^void (id x) {
        NSLog(@"%@:x:%@", NSStringFromSelector(_cmd), x);
    };
    // 2.订阅信号
    [signal subscribeNext:doSomethingWhenReceiveSignal];
}

注意上述代码中的注释,可以按照如下的描述:

1.创建信号的时候,需要保存一个blockA(此block的作用是:当订阅信号的时候,需要做的事情)
2.订阅信号的时候,需要保存一个blockB(此block的作用是:当收到信号发送值的时候,需要做的事情)

如果在设计代码的时候我们就会这样考虑设计:

1.信号会一直持有blockA,理论上订阅一个信号的时候,订阅所做的事情都是一样的

2.信号不会持有blockB,一个订阅信号,然后收到信号发送值的时候,处理的事情是不同的。

如下的3个关键函数的实现:

1.创建信号:[RACSignal createSignal...]

RACSignal.m
创建一个RACDynamicSignal的实例,就是把blockA当做参数传递给RACDynamicSignal

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

RACDynamicSignal.m
直接简单的保存blockA

+ (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe {
    RACDynamicSignal *signal = [[self alloc] init];
    signal->_didSubscribe = [didSubscribe copy];
    return [signal setNameWithFormat:@"+createSignal:"];
}
2.订阅信号:[signal subscribeNext...]

RACSignal.m
用函数B创建一个订阅者RACSubscriber,信号订阅订阅者([self subscribe:o]字面理解),或者说用这个订阅者处理此信号,信号没有持有blockB

- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
    NSCParameterAssert(nextBlock != NULL);
    
    RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
    return [self subscribe:o];
}

RACSubscriber.m
RACSubscriber持有了blockB

+ (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;
}

RACDynamicSignal.m
订阅者处理信号,里面有一堆复杂的,但是关键的就是:self.didSubscribe(subscriber),表明调用了blockA

- (RACDisposable *)subscribe:(id)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);
            [disposable addDisposable:innerDisposable];
        }];

        [disposable addDisposable:schedulingDisposable];
    }
    
    return disposable;
}
3.发送信号:[subscriber sendNext...]

RACSubscriber.m
发送信号的时候,就是直接使用blockB

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

        nextBlock(value);
    }
}

在整个RAC实现的过程中订阅者都是被隐藏的,都是通过一个协议去实现的:


image.png

具体看里面的定义就知道了。

你可能感兴趣的:(RAC源码解析)