1

我厂广招各路大神加入:job.koudaitong.com
可以发简历到 tianchi@qima-inc.com O(∩_∩)O~

Performing side effects with signals

//实在不知道side effects应该翻译成什么,从网上找的资料来看应该是一个专有名词。
大多数信号一开始是“冷”的,意思是,它们不做任何事直到有人订阅。

在订阅时,信号或者它的订阅者可以执行side effects,比如在控制台打印(logging to the console)、发起一个网络请求(marking a network request)、更新UI等等。

side effects也能够被注入到一个信号中去,在那里它将不会立即执行而是将在每个订阅之后执行。

Subscription

-subscribe...方法能够让你访问到信号中当前或者之后(future)的值:

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

对于一个“冷”信号,side effects会在每一次订阅的时候执行:

__block unsigned subscriptions = 0;

RACSignal *loggingSignal = [RACSignal createSignal:^ RACDisposable * (id<RACSubscriber> subscriber) {
    subscriptions++;
    [subscriber sendCompleted];
    return nil;
}];

// Outputs:
// subscription 1
[loggingSignal subscribeCompleted:^{
    NSLog(@"subscription %u", subscriptions);
}];

// Outputs:
// subscription 2
[loggingSignal subscribeCompleted:^{
    NSLog(@"subscription %u", subscriptions);
}];  

这种行为可以通过Connection来改变。

Injecting effects

-do...方法将side effects添加到信号中而不实际地订阅它:

__block unsigned subscriptions = 0;

RACSignal *loggingSignal = [RACSignal createSignal:^ RACDisposable * (id<RACSubscriber> subscriber) {
    subscriptions++;
    [subscriber sendCompleted];
    return nil;
}];

// Does not output anything yet
loggingSignal = [loggingSignal doCompleted:^{
    NSLog(@"about to complete subscription %u", subscriptions);
}];

// Outputs:
// about to complete subscription 1
// subscription 1
[loggingSignal subscribeCompleted:^{
    NSLog(@"subscription %u", subscriptions);
}];  

Transforming streams--改变流

这些操作将一个流变为一个新的流。

Mapping

-map:方法用来改变流中的值并用结果创建一个新的流:

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

// Contains: AA BB CC DD EE FF GG HH II
RACSequence *mapped = [letters map:^(NSString *value) {
    return [value stringByAppendingString:value];
}];

Filtering

filter:方法用一个block来判断(test)每一个值,如果判断通过则把这个值加入到结果的流(resulting stream)中:

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

// Contains: 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;

// Contains: 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方法用来将包含多个流的流(stream-of-streams)合并成一个流:

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;

// Contains: 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];

// Outputs: 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:方法被用来将流中的每个值加入到一个新的流中。然后所有返回的流将被压缩成一个流。相当于在-map:之后进行-flatten:

这可以用来修改或者扩展序列:

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

// Contains: 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;
}];

// Contains: 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

这些方法用来组合多个信号并生成一个新的信号。

Sequencing

-then:启动原始的信号,等待它完成,之后只传递值到一个新的信号:

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

// The new signal only contains: 1 2 3 4 5 6 7 8 9
//
// But when subscribed to, it also outputs: 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;
    }];

这对于执行一个信号的所有side effects然后开始另一个信号并且只返回第二个信号的值很有用。

Merging

+merge:方法会在有新的值到达的时候把这些从多个信号中来的值加入到一个流中:

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

// Outputs: 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:方法会观察(watch)多个信号的变化,然后在一个变化发生的时候向那些信号发送最新的值。

RACSubject *letters = [RACSubject subject];
RACSubject *numbers = [RACSubject subject];
RACSignal *combined = [RACSignal
combineLatest:@[ letters, numbers ]
   reduce:^(NSString *letter, NSString *number) {
   return [letter stringByAppendingString:number];
}];

// Outputs: 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"];

注意:组合的信号(combined signal)只会在所有的输入至少都有一个值的时候才会发送它的第一个值,比如上面代码中@"A"没有被输出因为numbers还没有收到一个值。

Switching

-switchToLatest方法用于含有多个信号的信号(signal-of-signals),它总是输出(forwards)最新的信号的值。

RACSubject *letters = [RACSubject subject];
RACSubject *numbers = [RACSubject subject];
RACSubject *signalOfSignals = [RACSubject subject];

RACSignal *switched = [signalOfSignals switchToLatest];

// Outputs: 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"];

EscapedDog
192 声望24 粉丝

objcer