ReactiveCocoa源码拆分解析(二)

(整个关于ReactiveCocoa的代码工程可以在https://github.com/qianhongqiang/QHQReactive下载)

上面抽丝剥茧的把最主要的信号机制给分离开了。但在RAC中各种操作也是必不可少的,一些复杂的操作符也是有一些基础操作拼接组合而来,有点搭积木的味道。

那我沿着之前的思路,写一些简单的操作符是如何实现的。

 

操作符之concat(拼接)

concat 使用示例

    QHQSignal *demoOriginSignal = [QHQSignal createSignal:^(id subscriber) {

        [subscriber sendNext:@"demoOriginSignal - send"];

        [subscriber sendCompleted];

    }];

    

    QHQSignal *demoConcatSignal = [QHQSignal createSignal:^(id subscriber) {

        [subscriber sendNext:@"demoConcatSignal - send"];

    }];

    

    [[demoOriginSignal concat:demoConcatSignal] subscribeNext:^(id x) {

        NSLog(@"%@",x);

    }];

输出内容

2015-12-25 10:02:45.966 PageText[88233:4685875] demoOriginSignal - send

2015-12-25 10:02:45.967 PageText[88233:4685875] demoConcatSignal - send

达到了拼接的效果

实现思路很简单,就是在第一个信号sendcompleted的时候,让subscirber订阅被拼接的信号。

-(QHQSignal *)concat:(QHQSignal *)concatSignal {

    return [QHQSignal createSignal:^(id subscriber) {

        [self subscribeNext:^(id next) {

            [subscriber sendNext:next];

        } error:^(NSError *error) {

            [subscriber sendError:error];

        } completed:^{

            [concatSignal subscribe:subscriber];

        }];

    }];

}

可以看当self(源信号)发送next时,新信号也发送next,发送error,新信号也发送error。发送completed时,让订阅着订阅了被拼接的信号,这样就实现了拼接。

 

再实现一个复杂些的操作符zip,zip的作用是将2个信号进行压缩。每当2个信号都有新值来时,将两个新值以元组形势返回,demo中以数组返回。(元组可参见swift,这里rac以宏实现了元组的操作)。

QHQSignal *demoOriginSignal = [QHQSignal createSignal:^(id subscriber) {

        [subscriber sendNext:@"demoOriginSignal - send- zip1"];

        [subscriber sendNext:@"demoOriginSignal - send- zip2"];

    }];

    

    QHQSignal *demoConcatSignal = [QHQSignal createSignal:^(id subscriber) {

        [subscriber sendNext:@"demoConcatSignal - send - zip1"];

        [subscriber sendNext:@"demoConcatSignal - send - zip2"];

    }];

    

    [[demoOriginSignal zip:demoConcatSignal] subscribeNext:^(id x) {

        NSLog(@"%@",x);

    }];

输出结果

2015-12-25 11:10:44.546 PageText[89544:4713950] (

    "demoOriginSignal - send- zip1",

    "demoConcatSignal - send - zip1"

)

2015-12-25 11:10:44.547 PageText[89544:4713950] (

    "demoOriginSignal - send- zip2",

    "demoConcatSignal - send - zip2"

)


注释掉任意一个send后,都将减少一次输出,如果某个信号不发送内容,那么将不会有输出。

 

-(QHQSignal *)zip:(QHQSignal *)signal {

    

    return [QHQSignal createSignal:^(id subscriber) {

        NSMutableArray *selfArray = [NSMutableArray array];

        NSMutableArray *zipArray = [NSMutableArray array];

        

        void (^sendZip)(void) = ^{

            if (selfArray.count == 0) return;

            if (zipArray.count == 0) return;

            

            NSArray *send = [NSArray arrayWithObjects:selfArray.firstObject, zipArray.firstObject,nil];;

            

            [selfArray removeObjectAtIndex:0];

            [zipArray removeObjectAtIndex:0];

            

            [subscriber sendNext:send];

            

        };

        

        [self subscribeNext:^(id x) {

            [selfArray addObject:x];

            sendZip();

        }];

        

        [signal subscribeNext:^(id x) {

            [zipArray addObject:x];

            sendZip();

        }];

    }];

    

}

源码展示:压缩后的信号用两个数组表示压缩前信号的值。直到都有值时,才将信号打包输出。都是比较简单的实现。

 

剩下操作的可以自己根据源码分析用途了,明白了原理,用起来也更放心。

posted @ 2015-12-25 11:15  钱鸿强  阅读(241)  评论(0编辑  收藏  举报