美文网首页
ReactiveCocoa 使用.RACSubject类使用

ReactiveCocoa 使用.RACSubject类使用

作者: 土豆萝卜君 | 来源:发表于2017-08-31 17:52 被阅读0次

    我们知道只要创建一个信号,在有一个订阅者去订阅她我们就可以发送消息了。但是有没有一个对象既可以发送消息又可以订阅消息呢? 这时候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<RACSubscriber>)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<RACSubscriber> 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<RACSubscriber> subscriber) {
            [subscriber sendNext:value];
        }];
    }
    
    • 先遍历订阅者数组中的订阅者
    • 后执行订阅者中的nextBlock
    • 订阅者发送信号

    借用他们的流程图为

    1467716-f2b4f5f91210d0ba.png

    相关文章

      网友评论

          本文标题:ReactiveCocoa 使用.RACSubject类使用

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