ReactiveCocoa 使用.RACSubject类使用

我们知道只要创建一个信号,在有一个订阅者去订阅她我们就可以发送消息了。但是有没有一个对象既可以发送消息又可以订阅消息呢? 这时候RACSubject 就出现了,因为它继承与RACSignal信号类又遵守RACSubscribe协议这样达到了就既能发送,又能订阅信号的操作了。他的使用场景可以做为代理来使用 或者 用来绑定ViewModel和View

RACSubject
- (void)subjectTest {
    
    RACSubject *subject = [RACSubject subject];
    // 2.订阅信号(这里可以创建多个订阅者)
    [subject subscribeNext:^(id x) {
        // block调用时刻:当信号发出新值,就会调用.
        NSLog(@"第一个订阅者%@",x);
    }];
    [subject subscribeNext:^(id x) {
        // block调用时刻:当信号发出新值,就会调用.
        NSLog(@"第二个订阅者%@",x);
    }];
    [subject subscribeNext:^(id x) {
        // block调用时刻:当信号发出新值,就会调用.
        NSLog(@"第三个订阅者%@",x);
    }];
    // 3.发送信号
    [subject sendNext:@"1"];
}
RACReplaySubject
  • 可以先订阅信号,也可以先发送信号
  • 调用sendNext发送信号,把值保存起来,然后遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock。
  • 调用subscribeNext订阅信号,遍历保存的所有值,一个一个调用订阅者的nextBlock
    如果想当一个信号被订阅,就重复播放之前所有值,需要先发送信号,在订阅信号。
- (void)replaySubjectTest{
RACReplaySubject *replaySubject = [RACReplaySubject subject];
    
    // 2.发送信号
    [replaySubject sendNext:@1];
    [replaySubject sendNext:@2];
    
    // 3.订阅信号
    [replaySubject subscribeNext:^(id x) {
        
        NSLog(@"第一个订阅者接收到的数据%@",x);
    }];
    
    // 订阅信号
    [replaySubject subscribeNext:^(id x) {
        
        NSLog(@"第二个订阅者接收到的数据%@",x);
    }];
}

上一篇讲解了下RACSignal内部的流程,知道了RACSignal在看RACSubject就简单很多了,毕竟是RACSubject继承与RACSignal,一些方法都是大同小异的。

1 创建信号
+ (instancetype)subject {
    return [[self alloc] init];
}

- (id)init {
    self = [super init];
    if (self == nil) return nil;

    _disposable = [RACCompoundDisposable compoundDisposable];
    _subscribers = [[NSMutableArray alloc] initWithCapacity:1];
    
    return self;
}

  • 创建RACSubject对象的时候同时创建了相应的一个disposable和一个订阅者数组,仅仅而已
2 订阅信号
- (RACDisposable *)subscribe:(id)subscriber {
    NSCParameterAssert(subscriber != nil);

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

    NSMutableArray *subscribers = self.subscribers;
    @synchronized (subscribers) {
        [subscribers addObject:subscriber];
    }
    
    return [RACDisposable disposableWithBlock:^{
        @synchronized (subscribers) {
            // Since newer subscribers are generally shorter-lived, search
            // starting from the end of the list.
            NSUInteger index = [subscribers indexOfObjectWithOptions:NSEnumerationReverse passingTest:^ BOOL (id obj, NSUInteger index, BOOL *stop) {
                return obj == subscriber;
            }];

            if (index != NSNotFound) [subscribers removeObjectAtIndex:index];
        }
    }];
}
  • RACSubejct是可以多次订阅的 它把生产的订阅者存入订阅者数组中,每个订阅者都包含自己的对应的block(next,error,complete)
  • 它比RACSignal取消的时候多做了一些清理工作,把订阅者数组中的相对于的订阅者去除并取消
3 发送信号
- (void)sendNext:(id)value {
    [self enumerateSubscribersUsingBlock:^(id subscriber) {
        [subscriber sendNext:value];
    }];
}
  • 先遍历订阅者数组中的订阅者
  • 后执行订阅者中的nextBlock
  • 订阅者发送信号

借用他们的流程图为

ReactiveCocoa 使用.RACSubject类使用_第1张图片
1467716-f2b4f5f91210d0ba.png

你可能感兴趣的:(ReactiveCocoa 使用.RACSubject类使用)