美文网首页
RAC中的reduceEach

RAC中的reduceEach

作者: 一只二进制编码的狗 | 来源:发表于2016-01-28 14:52 被阅读683次

    前面可以看到RAC中的zip和combineLatest最后都会走到reduceEach,这个RACStream中的方法,来看源码:

    - (instancetype)reduceEach:(id (^)())reduceBlock {
        NSCParameterAssert(reduceBlock != nil);
    
        __weak RACStream *stream __attribute__((unused)) = self;
        return [[self map:^(RACTuple *t) {
            NSCAssert([t isKindOfClass:RACTuple.class], @"Value from stream %@ is not a tuple: %@", stream, t);
            return [RACBlockTrampoline invokeBlock:reduceBlock withArguments:t];
        }] setNameWithFormat:@"[%@] -reduceEach:", self.name];
    }
    

    打了断言就是数据类型必须封装为RACTuple,核心代码为RACBlockTrampoline:

    //初始化,没啥说的
    - (id)initWithBlock:(id)block {
        self = [super init];
        if (self == nil) return nil;
    
        _block = [block copy];
    
        return self;
    }
    
    + (id)invokeBlock:(id)block withArguments:(RACTuple *)arguments {
        NSCParameterAssert(block != NULL);
    
        RACBlockTrampoline *trampoline = [[self alloc] initWithBlock:block];
        return [trampoline invokeWithArguments:arguments];
    }
    
    - (id)invokeWithArguments:(RACTuple *)arguments {
    //根据RACTuple的个数选择selector,最多支持15个,也就是你combineLatest最多只能有15个信号
        SEL selector = [self selectorForArgumentCount:arguments.count];
    //NSInvocation可以单纯的理解为执行一个方法,比performSelector强大,因为他可以带很多参数进去
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:selector]];
        invocation.selector = selector;
        invocation.target = self;
    
        for (NSUInteger i = 0; i < arguments.count; i++) {
    //把参数带进去
            id arg = arguments[i];
            NSInteger argIndex = (NSInteger)(i + 2);
            [invocation setArgument:&arg atIndex:argIndex];
        }
    
        [invocation invoke];
        
        __unsafe_unretained id returnVal;
        [invocation getReturnValue:&returnVal];
        return returnVal;
    }
    //写法不漂亮,也是无奈之举
    - (SEL)selectorForArgumentCount:(NSUInteger)count {
        NSCParameterAssert(count > 0);
    
        switch (count) {
            case 0: return NULL;
            case 1: return @selector(performWith:);
            case 2: return @selector(performWith::);
            case 3: return @selector(performWith:::);
            case 4: return @selector(performWith::::);
            case 5: return @selector(performWith:::::);
            case 6: return @selector(performWith::::::);
            case 7: return @selector(performWith:::::::);
            case 8: return @selector(performWith::::::::);
            case 9: return @selector(performWith:::::::::);
            case 10: return @selector(performWith::::::::::);
            case 11: return @selector(performWith:::::::::::);
            case 12: return @selector(performWith::::::::::::);
            case 13: return @selector(performWith:::::::::::::);
            case 14: return @selector(performWith::::::::::::::);
            case 15: return @selector(performWith:::::::::::::::);
        }
    
        NSCAssert(NO, @"The argument count is too damn high! Only blocks of up to 15 arguments are currently supported.");
        return NULL;
    }
    
    - (id)performWith:(id)obj1 {
        id (^block)(id) = self.block;
        return block(obj1);
    }
    
    - (id)performWith:(id)obj1 :(id)obj2 {
        id (^block)(id, id) = self.block;
        return block(obj1, obj2);
    }
    
    - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 {
        id (^block)(id, id, id) = self.block;
        return block(obj1, obj2, obj3);
    }
    
    - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 {
        id (^block)(id, id, id, id) = self.block;
        return block(obj1, obj2, obj3, obj4);
    }
    
    - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 {
        id (^block)(id, id, id, id, id) = self.block;
        return block(obj1, obj2, obj3, obj4, obj5);
    }
    
    - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 {
        id (^block)(id, id, id, id, id, id) = self.block;
        return block(obj1, obj2, obj3, obj4, obj5, obj6);
    }
    
    - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 {
        id (^block)(id, id, id, id, id, id, id) = self.block;
        return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7);
    }
    
    - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 {
        id (^block)(id, id, id, id, id, id, id, id) = self.block;
        return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8);
    }
    
    - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 {
        id (^block)(id, id, id, id, id, id, id, id, id) = self.block;
        return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9);
    }
    
    - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 {
        id (^block)(id, id, id, id, id, id, id, id, id, id) = self.block;
        return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10);
    }
    
    - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 {
        id (^block)(id, id, id, id, id, id, id, id, id, id, id) = self.block;
        return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11);
    }
    
    - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 :(id)obj12 {
        id (^block)(id, id, id, id, id, id, id, id, id, id, id, id) = self.block;
        return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12);
    }
    
    - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 :(id)obj12 :(id)obj13 {
        id (^block)(id, id, id, id, id, id, id, id, id, id, id, id, id) = self.block;
        return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12, obj13);
    }
    
    - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 :(id)obj12 :(id)obj13 :(id)obj14 {
        id (^block)(id, id, id, id, id, id, id, id, id, id, id, id, id, id) = self.block;
        return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12, obj13, obj14);
    }
    
    - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 :(id)obj12 :(id)obj13 :(id)obj14 :(id)obj15 {
        id (^block)(id, id, id, id, id, id, id, id, id, id, id, id, id, id, id) = self.block;
        return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12, obj13, obj14, obj15);
    }
    

    相关文章

      网友评论

          本文标题:RAC中的reduceEach

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