Reactivecoco 文档翻译(1) 基本操作方法

本文介绍了ReactiveCocoa的基本概念及应用,通过实例演示了如何使用信号(signal)和序列(sequence)进行流操作,包括创建、订阅、转换、过滤、合并等操作,并探讨了信号副作用的实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文:点这里
这个文档说明了一些经常使用的操作,并且有例子说明. 操作主要是运用序列(sequences)和信号(signal)的流(stream)操作.

Side Effect: 信号的副作用, 边际效应 (本人的理解..)

用信号实现信号的副作用

绝大多数信号创建的时候是 “冷信号”, 即直到信号被订阅后才能执行的信号. 在订阅的基础上, 信号或者订阅者可以执行一些信号的副作用方法, 比如输出一些log, 发起网络请求, 更新UI等等. 副作用方法也可以注入到信号中, 当然不会立即执行, 但是执行后会影响所有的订阅者.

订阅(Subscription)

在方法中带有前缀 -subscribe…的方法,可以从一个信号中获得当前和以后的值.

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

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

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

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

这些操作也可以使用 connenction来实现.

注入的影响 (信号内部的)

带有 -do...前缀的方法会产生副作用, 但是不会真的订阅信号

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

信号流转换

这些方法将一个信号转换成一个新的信号

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];
}];
[mapped.signal subscribeNext:^(id x) {
    NSLog(@"%@",x);
}];

Filtering 过滤

-filter方法使用了一个block来过滤每一个输入的值, 符合条件的值才能输出

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: 方法应用于从信号流到信号流的, 然后合并成一个新的流.

下面的序列是串行的:

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 合并信号

这些方法将多个信号合并成一个 RACSignal 对象

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

这个方法对于执行一个信号的所有副作用方法后, 再只执行另一个方法, 然后返回第二个信号的值 是很有用的.

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:方法会监听多个信号的值的变化,有一个值变化, 就将最新的值输出

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

注意: 合并信号后, 只有当所有的信号都至少发送了一个值的时候, 合并的信号才发出第一次信号值. 上面的例子中 “A” 不会输出, 因为 numbers 还没有第一次输出值

Switching 切换

-switchToLatest:方法会切换输入信号源来输出结果, 每次sendNext一个新的信号, 输出会按照新的信号输出,可以随时切换输入源的信号

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"];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值