美文网首页
RAC中的zip和combineLatest区别

RAC中的zip和combineLatest区别

作者: 一只二进制编码的狗 | 来源:发表于2016-01-20 16:02 被阅读2301次

    都是打包一堆信号,区别可从源码中看出:

    + (instancetype)zip:(id<NSFastEnumeration>)streams {
        return [[self join:streams block:^(RACStream *left, RACStream *right) {
            return [left zipWith:right];
        }] setNameWithFormat:@"+zip: %@", streams];
    }
    
    + (instancetype)zip:(id<NSFastEnumeration>)streams reduce:(id (^)())reduceBlock {
        NSCParameterAssert(reduceBlock != nil);
    
        RACStream *result = [self zip:streams];
    
        // Although we assert this condition above, older versions of this method
        // supported this argument being nil. Avoid crashing Release builds of
        // apps that depended on that.
        if (reduceBlock != nil) result = [result reduceEach:reduceBlock];
    
        return [result setNameWithFormat:@"+zip: %@ reduce:", streams];
    }
    
    + (RACSignal *)combineLatest:(id<NSFastEnumeration>)signals {
        return [[self join:signals block:^(RACSignal *left, RACSignal *right) {
            return [left combineLatestWith:right];
        }] setNameWithFormat:@"+combineLatest: %@", signals];
    }
    
    + (RACSignal *)combineLatest:(id<NSFastEnumeration>)signals reduce:(id (^)())reduceBlock {
        NSCParameterAssert(reduceBlock != nil);
    
        RACSignal *result = [self combineLatest:signals];
    
        // Although we assert this condition above, older versions of this method
        // supported this argument being nil. Avoid crashing Release builds of
        // apps that depended on that.
        if (reduceBlock != nil) result = [result reduceEach:reduceBlock];
    
        return [result setNameWithFormat:@"+combineLatest: %@ reduce:", signals];
    }
    

    可见区别主要在return,则可以把焦点放到combineLatestWith:和zipWith:两个方法中

    return [left combineLatestWith:right];
    return [left zipWith:right];
    

    zipwith方法的源码:

    - (RACSignal *)zipWith:(RACSignal *)signal {
        NSCParameterAssert(signal != nil);
           //创建一个新的信号
        return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
            __block BOOL selfCompleted = NO;
            NSMutableArray *selfValues = [NSMutableArray array];
    
            __block BOOL otherCompleted = NO;
            NSMutableArray *otherValues = [NSMutableArray array];
    
            void (^sendCompletedIfNecessary)(void) = ^{
                @synchronized (selfValues) {
                    BOOL selfEmpty = (selfCompleted && selfValues.count == 0);
                    BOOL otherEmpty = (otherCompleted && otherValues.count == 0);
                    if (selfEmpty || otherEmpty) [subscriber sendCompleted];
                }
            };
    
            void (^sendNext)(void) = ^{
                @synchronized (selfValues) {
                                    //self和signal都有值才send next
                    if (selfValues.count == 0) return;
                    if (otherValues.count == 0) return;
    
                    RACTuple *tuple = RACTuplePack(selfValues[0], otherValues[0]);
    //发送的值为各自数组的第一个值,这也是和combineLastWith最大的区别
                    [selfValues removeObjectAtIndex:0];
                    [otherValues removeObjectAtIndex:0];
    
                    [subscriber sendNext:tuple];
                    sendCompletedIfNecessary();
                }
            };
    
            RACDisposable *selfDisposable = [self subscribeNext:^(id x) {
                @synchronized (selfValues) {
    //订阅原始信号,如果有值则添加到selfValues
                    [selfValues addObject:x ?: RACTupleNil.tupleNil];
                    sendNext();
                }
            } error:^(NSError *error) {
                [subscriber sendError:error];
            } completed:^{
                @synchronized (selfValues) {
                    selfCompleted = YES;
                    sendCompletedIfNecessary();
                }
            }];
    
            RACDisposable *otherDisposable = [signal subscribeNext:^(id x) {
                @synchronized (selfValues) {
    //订阅传进来的信号,如果有值则添加到otherValues
                    [otherValues addObject:x ?: RACTupleNil.tupleNil];
                    sendNext();
                }
            } error:^(NSError *error) {
                [subscriber sendError:error];
            } completed:^{
                @synchronized (selfValues) {
                    otherCompleted = YES;
                    sendCompletedIfNecessary();
                }
            }];
    
            return [RACDisposable disposableWithBlock:^{
                [selfDisposable dispose];
                [otherDisposable dispose];
            }];
        }] setNameWithFormat:@"[%@] -zipWith: %@", self.name, signal];
    }
    

    combineLatestWith方法源码:

    - (RACSignal *)combineLatestWith:(RACSignal *)signal {
        NSCParameterAssert(signal != nil);
    
        return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
            RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
    
            __block id lastSelfValue = nil;
            __block BOOL selfCompleted = NO;
    
            __block id lastOtherValue = nil;
            __block BOOL otherCompleted = NO;
    
            void (^sendNext)(void) = ^{
                @synchronized (disposable) {
    //只发送最近的一个值,而不是像zipwith维护一个数组,去数组的第一个值
                    if (lastSelfValue == nil || lastOtherValue == nil) return;
                    [subscriber sendNext:RACTuplePack(lastSelfValue, lastOtherValue)];
                }
            };
    
            RACDisposable *selfDisposable = [self subscribeNext:^(id x) {
                @synchronized (disposable) {
                    lastSelfValue = x ?: RACTupleNil.tupleNil;
                    sendNext();
                }
            } error:^(NSError *error) {
                [subscriber sendError:error];
            } completed:^{
                @synchronized (disposable) {
                    selfCompleted = YES;
                    if (otherCompleted) [subscriber sendCompleted];
                }
            }];
    
            [disposable addDisposable:selfDisposable];
    
            RACDisposable *otherDisposable = [signal subscribeNext:^(id x) {
                @synchronized (disposable) {
                    lastOtherValue = x ?: RACTupleNil.tupleNil;
                    sendNext();
                }
            } error:^(NSError *error) {
                [subscriber sendError:error];
            } completed:^{
                @synchronized (disposable) {
                    otherCompleted = YES;
                    if (selfCompleted) [subscriber sendCompleted];
                }
            }];
    
            [disposable addDisposable:otherDisposable];
    
            return disposable;
        }] setNameWithFormat:@"[%@] -combineLatestWith: %@", self.name, signal];
    }
    

    总结:
    逻辑大致相同,有各自应用场景

    相关文章

      网友评论

          本文标题:RAC中的zip和combineLatest区别

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