ReactiveCocoa的流和序列

2018-08-01 14:28 更新

ReactiveCocoa中的流是值的序列化的抽象,一个流可以被当成一条通道,而值就是通道中传输的物质,值从通道的一头进入再从另一头出来。只要值从通道的另一头流出来了,我们就可以对过去的所有值进行读取,对于刚刚进入通道的值(即当前值)也是可以读取的。还有比较难理解的就是值的序列化了,那么按照我们当前的理解程度来说,它像是一个数组、一个列表。

事实上,使用rac_sequeuece我们能够轻松地将数组转化为一个流:

NSArray *array = @[ @1, @2, @3 ];
RACSequence * stream = [array rac_sequence];

等一下!Sequences?我以为我们在处理Stream? 好吧,说明一下,Sequences是两种特定类型的流的一种,实际上,RACSequence是一个RACStream的子类。 我们能用流做什么呢?好吧,我将使用流来展示上一章中提到的例子。应用在平方数映射上:

[stream map:^id (id value){
    return @(pow([value integerValue], 2));
}];

注意,跟数组一样,流不能包含nil元素。[译者注:NSArray中以nil作为结束标示,stream也一样]。 非常好!但是流映射后还是流,我们怎么样才能得到数组呢?幸运的是,RACSequence有一个方法返回数组:array

NSLog(@"%@",[stream array]);

这会打印映射后的数组。比起直接使用RXCollections这多出了几个步骤,但这里我只想说明使用流也可以达成任务。

当然,我们可以合并上面的方法调用来避免污染变量的作用域.

NSLog(@"%@",[[[array rac_sequence] map:^id (id value){
                    return @(pow([value integerValue], 2));
                }] array]);

总的来说,我们做了这样的事情:

  • 将数组转化成一个序列类型的流。
  • 对流进行映射得到一个新的流。
  • 将新的流转为数组。

序列,默认情况下是延迟加载的(也称:懒加载或被动加载),是pull-driven的,在他们被生成的时候就会提供确切的值,而数组方法会强制给序列的每一个成员赋值。

我们来看一下filtering。为了使用ReactiveCocoa来过滤我们的数组,我们需要再一次把它序列化以便于使用过滤。

NSLog(@"%@", [[[array rac_sequence] filter:^BOOL (id value){
                        return [value integerValue] % 2 == 0;
                    }] array]);

最后看一下怎么让一个序列流合并为单个值(folding):

NSLog(@"%@",[[[array rac_sequence] map:^id (id value){
                    return [value stringValue];
                }] foldLeftWithStart:@"" reduce:^id (id accumulator, id value){
                    return [accumulator stringByAppendingString:value];
            }]);

这种情况下,我们在序列上进行了链式调用,当我们讨论下一节'信号'的时候,(链式调用)是一个关键的概念。

ReactiveCocoa具有左折叠和右折叠的概念。左折叠时折叠算法将从头到尾遍历数组,反之称为右折叠。这样的命名(即左、右折叠)暗示了编程语言对列表的理解,这种概念在Objective-C中是没有的。

确定你现在已经理解了到此为止我们所说的内容,因为这对后面的讲解内容十分重要。


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号