美文网首页
ReactiveCocoa基本运算符

ReactiveCocoa基本运算符

作者: 丘山Ivan | 来源:发表于2017-11-27 12:00 被阅读18次

基本运算符

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

序列信号所共同使用的运算符被称之为运算符.

订阅信号执行自定义操作

  1. 订阅信号
  2. 注入自定义操作

转换流

  1. 映射
  2. 过滤

合并流

  1. 串联
  2. 降维
  3. 映射和降维

合并信号

  1. sequence
  2. 合并
  3. 合并最新信号
  4. 开关

订阅信号执行自定义操作

大多数信号都是'冷'的,这意味着:直到有订阅产生,他们才会产生信号.

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

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

订阅(Subscription)

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

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);
}];

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

__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);
}];

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

注入自定义操作(Injecting effects)

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

__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:方法,可以将一个流中的值映射成一个新的值,并返回一个带有新值的流:

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:将通过一个block来检查流中的每一个值,并返回一个包含每个符合要求的值的新的流:

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:方法,可以将一个流和另外一个流串联起来:

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消息,可以将这个流中的流的值取出并返回一个新的流.

序列将被串联:

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];

信号将被合并:

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)

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

-flattenMap:被用来转换每个流的值,然后再返回包含这个值的信号到一个新的流中.然后将对这个流降维,也就是说先-map:-flatten.

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

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]; 
    }
}];

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

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 *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:]给一个信号注入自定义操作,然后当自定义操作完成时返回一个信号,十分方便.

合并(Merging)

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

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:+combineLatest:reduce:会观察所有多个信号(signal),当所有的信号(signal)都发生变化时,发送所有最新的所有的他们的值。

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被流的流使用,而且总是转发最新的信号。

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"];

转自:ReactiveCocoaChineseResources

相关文章

网友评论

      本文标题:ReactiveCocoa基本运算符

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