zoukankan      html  css  js  c++  java
  • ReactiveCocoa 源码阅读记录。

    1:RACSingle 需要订阅信号

     1     RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
     2         [subscriber sendNext:@"1"];
     3         [subscriber sendCompleted];
     4         return nil;
     5     }];
     6     
     7     [signal subscribeNext:^(id x) {
     8         
     9     } error:^(NSError * _Nullable error) {
    10         
    11     } completed:^{
    12         
    13     }];
    14 /*************    对应的源码    **************/
    15 // 生成RACDynamicSignal。即生成RACSignal的子类
    16 + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
    17     return [RACDynamicSignal createSignal:didSubscribe];
    18 }
    19 
    20 // 在子类中保存 didSubscribe block, 每一次订阅都会执行
    21 + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
    22     RACDynamicSignal *signal = [[self alloc] init];
    23     signal->_didSubscribe = [didSubscribe copy];
    24     return [signal setNameWithFormat:@"+createSignal:"];
    25 }
    26 
    27 /// 在订阅时执行保存在RACDynamicSignal中的didSubscribe block
    28 - (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
    29     NSCParameterAssert(subscriber != nil);
    30 
    31     RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
    32     subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
    33 
    34     if (self.didSubscribe != NULL) {
    35         RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
    36             RACDisposable *innerDisposable = self.didSubscribe(subscriber);
    37             [disposable addDisposable:innerDisposable];
    38         }];
    39 
    40         [disposable addDisposable:schedulingDisposable];
    41     }
    42     
    43     return disposable;
    44 }
    45 
    46 // 生成订阅者。并调用RACDynamicSignal中的订阅方法,执行didSubscribe block
    47 - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
    48     NSCParameterAssert(nextBlock != NULL);
    49     
    50     RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
    51     return [self subscribe:o];
    52 }
    53 
    54 // 生成的订阅者中保存 nextBlock, errorBlock, completedBlock.
    55 + (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed {
    56     RACSubscriber *subscriber = [[self alloc] init];
    57 
    58     subscriber->_next = [next copy];
    59     subscriber->_error = [error copy];
    60     subscriber->_completed = [completed copy];
    61 
    62     return subscriber;
    63 }
    64 
    65 // 当订阅者收到sendNext方法时,就会执行nextBlock
    66 - (void)sendNext:(id)value {
    67     @synchronized (self) {
    68         void (^nextBlock)(id) = [self.next copy];
    69         if (nextBlock == nil) return;
    70 
    71         nextBlock(value);
    72     }
    73 }

    2 RACSubject 既能订阅信号又能发送信号。 必须先订阅在发送。不然由于在sendNext时还没有订阅者会无法触发。

    1    /// 事例    
    2     RACSubject *sub = [[RACSubject alloc] init];
    3     [sub subscribeNext:^(id  _Nullable x) {
    4         NSLog(@"%@", a);
    5     }];
    6     
    7     [sub sendNext:@"a"];
     1 //调用时和RACSignal有区别的方法
     2 // 使用 subscribers 保存 订阅者。(RACDynamicSignal 还要执行didSubscrbe Block)
     3 - (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
     4     NSCParameterAssert(subscriber != nil);
     5 
     6     RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
     7     subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
     8 
     9     NSMutableArray *subscribers = self.subscribers;
    10     @synchronized (subscribers) {
    11         [subscribers addObject:subscriber];
    12     }
    13     
    14     [disposable addDisposable:[RACDisposable disposableWithBlock:^{
    15         @synchronized (subscribers) {
    16             // Since newer subscribers are generally shorter-lived, search
    17             // starting from the end of the list.
    18             NSUInteger index = [subscribers indexOfObjectWithOptions:NSEnumerationReverse passingTest:^ BOOL (id<RACSubscriber> obj, NSUInteger index, BOOL *stop) {
    19                 return obj == subscriber;
    20             }];
    21 
    22             if (index != NSNotFound) [subscribers removeObjectAtIndex:index];
    23         }
    24     }]];
    25 
    26     return disposable;
    27 }
    28 
    29 // 找到需要的订阅者
    30 - (void)enumerateSubscribersUsingBlock:(void (^)(id<RACSubscriber> subscriber))block {
    31     NSArray *subscribers;
    32     @synchronized (self.subscribers) {
    33         subscribers = [self.subscribers copy];
    34     }
    35 
    36     for (id<RACSubscriber> subscriber in subscribers) {
    37         block(subscriber);
    38     }
    39 }
    40 
    41 // 这行nextBlock。
    42 - (void)sendNext:(id)value {
    43     [self enumerateSubscribersUsingBlock:^(id<RACSubscriber> subscriber) {
    44         [subscriber sendNext:value];
    45     }];
    46 }

     3 bind bind是RAC中map,merge, flatten, flattenMap的基础

        flattenMap 实际上就是调用bind。 经过flattenMap映射后,subscribe的是block(value)即block里面的信号

      map 调用的flattenMap 经过Map映射后 subscribe的是[self return:block(value)]的信号假定为wrapSignal.而不是block(value)的信号假定为子信号。

        flatten 调用的是flattenMap,subscribe的子信号。调用flatten订阅到的值必须是一个Signal。

     1     RACSignal *returnSig = [RACSignal return:@"8"];
     2     RACSignal *bindSig = [returnSig bind:^RACSignalBindBlock {
     3         return ^RACSignal * (id value, BOOL *bl) {
     4             return [RACSignal return:value];
     5         };
     6     }];
     7     
     8     [bindSig subscribeNext:^(id  _Nullable x) {
     9         NSLog(@"%@", x);
    10     }];
    11     /*
    12      * -bind: should:
    13      * 订阅原始信号,并将订阅到的原始信号值,赋值给binding block。如果binding block返回了新的信号。订阅它, 之后用生成的中转信号的订阅者,执行返回的信号的sendNext方法和 sendComplete方法
    14      * 1. Subscribe to the original signal of values.
    15      * 2. Any time the original signal sends a value, transform it using the binding block.
    16      * 3. If the binding block returns a signal, subscribe to it, and pass all of its values through to the subscriber as they're received.
    17      * 4. If the binding block asks the bind to terminate, complete the _original_ signal.
    18      * 5. When _all_ signals complete, send completed to the subscriber.
    19      *
    20      * If any signal sends an error at any point, send that to the subscriber.
    21      */
    22 
    23     /*
    24     - (RACSignal *)bind:(RACSignalBindBlock (^)(void))block {
    25         NSCParameterAssert(block != NULL);
    26      
    27         return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
    28             RACSignalBindBlock bindingBlock = block();
    29             
    30             __block volatile int32_t signalCount = 1;   // indicates self
    31             
    32             RACCompoundDisposable *compoundDisposable = [RACCompoundDisposable compoundDisposable];
    33             
    34             void (^completeSignal)(RACDisposable *) = ^(RACDisposable *finishedDisposable) {
    35                 if (OSAtomicDecrement32Barrier(&signalCount) == 0) {
    36                     [subscriber sendCompleted];
    37                     [compoundDisposable dispose];
    38                 } else {
    39                     [compoundDisposable removeDisposable:finishedDisposable];
    40                 }
    41             };
    42             // signal 是bindingBlock返回的信号。订阅这个信号。由于在Block中有这个信号的sendNext方法故会直接执行他。之后接收到的值发送出去。
    43             void (^addSignal)(RACSignal *) = ^(RACSignal *signal) {
    44                 OSAtomicIncrement32Barrier(&signalCount);
    45                 
    46                 RACSerialDisposable *selfDisposable = [[RACSerialDisposable alloc] init];
    47                 [compoundDisposable addDisposable:selfDisposable];
    48                 
    49                 RACDisposable *disposable = [signal subscribeNext:^(id x) {
    50                     [subscriber sendNext:x];
    51                 } error:^(NSError *error) {
    52                     [compoundDisposable dispose];
    53                     [subscriber sendError:error];
    54                 } completed:^{
    55                     @autoreleasepool {
    56                         completeSignal(selfDisposable);
    57                     }
    58                 }];
    59                 
    60                 selfDisposable.disposable = disposable;
    61             };
    62             
    63             @autoreleasepool {
    64                 RACSerialDisposable *selfDisposable = [[RACSerialDisposable alloc] init];
    65                 [compoundDisposable addDisposable:selfDisposable];
    66                 // 订阅初始的信号(上面的returnSig), 执行bindingBLock,
    67                 RACDisposable *bindingDisposable = [self subscribeNext:^(id x) {
    68                     // Manually check disposal to handle synchronous errors.
    69                     if (compoundDisposable.disposed) return;
    70                     
    71                     BOOL stop = NO;
    72                     id signal = bindingBlock(x, &stop);
    73                     
    74                     @autoreleasepool {
    75                         if (signal != nil) addSignal(signal);
    76                         if (signal == nil || stop) {
    77                             [selfDisposable dispose];
    78                             completeSignal(selfDisposable);
    79                         }
    80                     }
    81                 } error:^(NSError *error) {
    82                     [compoundDisposable dispose];
    83                     [subscriber sendError:error];
    84                 } completed:^{
    85                     @autoreleasepool {
    86                         completeSignal(selfDisposable);
    87                     }
    88                 }];
    89                 
    90                 selfDisposable.disposable = bindingDisposable;
    91             }
    92             
    93             return compoundDisposable;
    94         }] setNameWithFormat:@"[%@] -bind:", self.name];
    95     }
    96 
    97     */
  • 相关阅读:
    前端安全
    关于HTTPS的概念性了解
    数组去重
    防抖与节流
    对meta标签的再次认识
    关于路由, 我好奇的那些点
    关于构造函数,实例,原型对象一纯手工的理解
    数据库查找操作-java
    python之图像加载和简单处理
    python之excel表格操作
  • 原文地址:https://www.cnblogs.com/jisa/p/10124238.html
Copyright © 2011-2022 走看看