RAC中经常使用的运算符 - 感谢听榆大叔的整理

来源:互联网 发布:java从入门到放弃 pdf 编辑:程序博客网 时间:2024/05/01 18:30

#基本运算符


本篇文档阐述了一些在RAC中经常使用的运算符,也包含了一些例子以说明他们的用法.


[序列][Sequences]__[信号][Signals]所共同使用的运算符被称之为[][Streams]运算符.

 

**[订阅信号执行自定义操作](#performing-side-effects-with-signals)**


 1. [订阅信号](#subscription)

 1. [注入自定义操作](#injecting-effects)


**[转换流](#transforming-streams)**


 1. [映射](#mapping)

 1. [过滤](#filtering)

 

**[合并流](#combining-streams)**


 1. [串联](#concatenating)

 1. [降维](#flattening)

 1. [映射和降维](#mapping-and-flattening)


**[合并信号](#combining-signals)**


 1. [sequence](#sequencing)

 1. [合并](#merging)

 1. [合并最新信号](#combining-latest-values)

 1. [开关](#switching)


##订阅信号执行自定义操作


大多数信号都是'',这意味着:直到有订阅产生,他们才会产生[信号](#subscription).


一旦有订阅产生,信号和[订阅者][Subscription]就能执行_自定义操作_,比如在命令行打印,网络请求,更新UI,等等.


自定义操作也能被[注入](#injecting-effects)到一个信号.这个操作也许不会被立即执行,但每当有订阅产生时,就会执行一次.


###订阅(Subscription)


通过[-subscribe…][RACSignal]方法,你可以订阅当前和将来的信号.


```objc

RACSignal *letters = [@"A B C D E F G H I" componentsSeparatedByString:@" "].rac_sequence.signal;


//输出: A B C D E F G H I

[letters subscribeNext:^(NSString *x) {

    NSLog(@"%@", x);

}];

```

对于''信号来说,_每当有订阅产生_,它的自定义操作就会执行一次.


```objc

__block unsigned subscriptions = 0;


RACSignal *loggingSignal = [RACSignal createSignal:^ RACDisposable * (id<RACSubscriber> subscriber) {

    subscriptions++;

    [subscriber sendCompleted];

    return nil;

}];


//输出:

//订阅 1

[loggingSignal subscribeCompleted:^{

    NSLog(@"订阅 %u", subscriptions);

}];


//输出:

//订阅 2

[loggingSignal subscribeCompleted:^{

    NSLog(@"订阅 %u", subscriptions);

}];

```


这种特性可以通过[连接][Connections]来改变.


###注入自定义操作(Injecting effects)


通过[-do…][RACSignal+Operations]方法,可以向信号注入自定义操作,而且不会产生一个订阅.


```objc

__block unsigned subscriptions = 0;


RACSignal *loggingSignal = [RACSignal createSignal:^ RACDisposable * (id<RACSubscriber> subscriber) {

    subscriptions++;

    [subscriber sendCompleted];

    return nil;

}];


//目前不会打印任何东西

loggingSignal = [loggingSignal doCompleted:^{

    NSLog(@"即将完成订阅 %u", subscriptions);

}];


//输出:

//即将完成订阅 1

//订阅 1

[loggingSignal subscribeCompleted:^{

    NSLog(@"订阅 %u", subscriptions);

}];

```


##转换流(Transforming streams)


以下操作符将一个流转换成另外一个流.


###映射(Mapping)


通过[-map:][RACStream]方法,可以将一个流中的值映射成一个新的值,并返回一个带有新值的流:


```objc

RACSequence *letters = [@"A B C D E F G H I" componentsSeparatedByString:@" "].rac_sequence;


//包括: AA BB CC DD EE FF GG HH II

RACSequence *mapped = [letters map:^(NSString *value) {

    return [value stringByAppendingString:value];

}];

```


###过滤(Filtering)


[-filter:][RACStream]将通过一个block来检查流中的每一个值,并返回一个包含每个符合要求的值的新的流:


```objc

RACSequence *numbers = [@"1 2 3 4 5 6 7 8 9" componentsSeparatedByString:@" "].rac_sequence;


//包含: 2 4 6 8

RACSequence *filtered = [numbers filter:^ BOOL (NSString *value) {

    return (value.intValue % 2) == 0;

}];

```


##合并流(Combining streams)


以下操作符将多个流合并成了一个新的流.


###串联(Concatenating)


通过[-concat:][RACStream]方法,可以将一个流和另外一个流串联起来:


```objc

RACSequence *letters = [@"A B C D E F G H I" componentsSeparatedByString:@" "].rac_sequence;

RACSequence *numbers = [@"1 2 3 4 5 6 7 8 9" componentsSeparatedByString:@" "].rac_sequence;


//包含: A B C D E F G H I 1 2 3 4 5 6 7 8 9

RACSequence *concatenated = [letters concat:numbers];

```


###降维(Flattening)


通过向一个包含流的流发送[-flatten][RACStream]消息,可以将这个流中的流的值取出并返回一个新的流.


序列将被[串联](#concatenating):


```objc

RACSequence *letters = [@"A B C D E F G H I" componentsSeparatedByString:@" "].rac_sequence;

RACSequence *numbers = [@"1 2 3 4 5 6 7 8 9" componentsSeparatedByString:@" "].rac_sequence;

RACSequence *sequenceOfSequences = @[ letters, numbers ].rac_sequence;


//包含: A B C D E F G H I 1 2 3 4 5 6 7 8 9

RACSequence *flattened = [sequenceOfSequences flatten];

```


信号将被[合并](#merging):


```objc

RACSubject *letters = [RACSubject subject];

RACSubject *numbers = [RACSubject subject];

RACSignal *signalOfSignals = [RACSignal createSignal:^ RACDisposable * (id<RACSubscriber> subscriber) {

    [subscriber sendNext:letters];

    [subscriber sendNext:numbers];

    [subscriber sendCompleted];

    return nil;

}];


RACSignal *flattened = [signalOfSignals flatten];


//输出: A 1 B C 2

[flattened subscribeNext:^(NSString *x) {

    NSLog(@"%@", x);

}];


[letters sendNext:@"A"];

[numbers sendNext:@"1"];

[letters sendNext:@"B"];

[letters sendNext:@"C"];

[numbers sendNext:@"2"];

```


###映射和降维(Mapping and flattening)


单独使用[降维](#flattening)并没有多大作用,但为了使用[-flattenMap:][RACStream]方法,理解它很重要.


`-flattenMap:`被用来转换每个流的值,然后再返回包含这个值的信号到一个_新的流_.然后将对这个流降维,也就是说先[-map:](#mapping)[-flatten](#flattening).


可以用来扩展或者编辑序列:


```objc

RACSequence *numbers = [@"1 2 3 4 5 6 7 8 9" componentsSeparatedByString:@" "].rac_sequence;


//包含: 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9

RACSequence *extended = [numbers flattenMap:^(NSString *num) {

    return @[ num, num ].rac_sequence;

}];


//包含: 1_ 3_ 5_ 7_ 9_

RACSequence *edited = [numbers flattenMap:^(NSString *num) {

    if (num.intValue % 2 == 0) {

        return [RACSequence empty];

    } else {

        NSString *newNum = [num stringByAppendingString:@"_"];

        return [RACSequence return:newNum]; 

    }

}];


```

或者是创建几个互相关联的信号:


```objc

RACSignal *letters = [@"A B C D E F G H I" componentsSeparatedByString:@" "].rac_sequence.signal;


[[letters

    flattenMap:^(NSString *letter) {

        return [database saveEntriesForLetter:letter];

    }]

    subscribeCompleted:^{

        NSLog(@"All database entries saved successfully.");

    }];

```


##合并信号(Combining signals)


These operators combine multiple signals into a single new [RACSignal][].


以下操作符将多个信号合并成一个新的信号.


### Sequencing


[-then:][RACSignal+Operations]将会触发对原本的信号触发一次订阅,当原本的信号完成时,产生一个新的信号.


```objc

RACSignal *letters = [@"A B C D E F G H I" componentsSeparatedByString:@" "].rac_sequence.signal;


//新的信号包含: 1 2 3 4 5 6 7 8 9

//

//但是当订阅产生时,他会打印: A B C D E F G H I

RACSignal *sequenced = [[letters

    doNext:^(NSString *letter) {

        NSLog(@"%@", letter);

    }]

    then:^{

        return [@"1 2 3 4 5 6 7 8 9" componentsSeparatedByString:@" "].rac_sequence.signal;

    }];

```


使用[[-doNext:][RACSignal+Operations]]给一个信号注入自定义操作,然后当自定义操作完成时返回一个信号,十分方便.


###合并(Merging)


[+merge:][RACSignal+Operations]将许多信号合并为一个新的信号,当每个信号有新的值时,它也将发送这个值:



```objc

RACSubject *letters = [RACSubject subject];

RACSubject *numbers = [RACSubject subject];

RACSignal *merged = [RACSignal merge:@[ letters, numbers ]];


//输出: A 1 B C 2

[merged subscribeNext:^(NSString *x) {

    NSLog(@"%@", x);

}];


[letters sendNext:@"A"];

[numbers sendNext:@"1"];

[letters sendNext:@"B"];

[letters sendNext:@"C"];

[numbers sendNext:@"2"];

```


###合并最新值 (Combining latest values)


[+combineLatest:][RACSignal+Operations] `+combineLatest:reduce:`会观察所有多个信号(signal),当_所有_的信号(signal)都发生变化时,发送所有最新的所有的他们的值。



```objc

RACSubject *letters = [RACSubject subject];

RACSubject *numbers = [RACSubject subject];

RACSignal *combined = [RACSignal

    combineLatest:@[ letters, numbers ]

    reduce:^(NSString *letter, NSString *number) {

        return [letter stringByAppendingString:number];

    }];


//打印: B1 B2 C2 C3

[combined subscribeNext:^(id x) {

    NSLog(@"%@", x);

}];


[letters sendNext:@"A"];

[letters sendNext:@"B"];

[numbers sendNext:@"1"];

[numbers sendNext:@"2"];

[letters sendNext:@"C"];

[numbers sendNext:@"3"];

```


我们注意到这个合并后的信号只会在他所有的输入产生变化时发送信号。上面的例子说明`@"A"`永远不会被转发,应为`numbers`并没有发送值。


###开关(Switching)


[-switchToLatest][RACSignal+Operations]被流的流使用,而且总是转发最新的信号。


```objc

RACSubject *letters = [RACSubject subject];

RACSubject *numbers = [RACSubject subject];

RACSubject *signalOfSignals = [RACSubject subject];


RACSignal *switched = [signalOfSignals switchToLatest];


//打印: A B 1 D

[switched subscribeNext:^(NSString *x) {

    NSLog(@"%@", x);

}];


[signalOfSignals sendNext:letters];

[letters sendNext:@"A"];

[letters sendNext:@"B"];


[signalOfSignals sendNext:numbers];

[letters sendNext:@"C"];

[numbers sendNext:@"1"];


[signalOfSignals sendNext:letters];

[numbers sendNext:@"2"];

[letters sendNext:@"D"];

```


[Connections]: FrameworkOverview.md#connections

[RACSequence]: ../ReactiveCocoa/RACSequence.h

[RACSignal]: ../ReactiveCocoa/RACSignal.h

[RACSignal+Operations]: ../ReactiveCocoa/RACSignal+Operations.h

[RACStream]: ../ReactiveCocoa/RACStream.h

[Sequences]: FrameworkOverview.md#sequences

[Signals]: FrameworkOverview.md#signals

[Streams]: FrameworkOverview.md#streams

[Subscription]: FrameworkOverview.md#subscription


0 0