RAC现在分了两部分,ReactiveCocoaObjc和ReactiveCocoaSwift,本文介绍的均是 ReactiveCocoaObjc 2.5.0 版本的内容.

RAC的核心是信号源(RACStream),在RAC中,信号源代表随着时间而改变的流值,订阅者通过订阅信号来获取这些值,RACStream是一个抽象类,我们用到的最多的是它的之类 RACSignal和RACSequence,
以下代码和示例使用的ReactiveCocoa 2.5版本

介绍RAC的操作之前先介绍以下链式操作

链式操作:

用过Masonry的同学应该对链式操作不陌生

1
2
3
4
5
6
7
8
9
[self.label mas_makeConstraints:^(MASConstraintMaker *make) {

make.top.left.mas_equalTo(0);

make.centerY.mas_equalTo(self.view);

make.width.height.mas_greaterThanOrEqualTo(0);

}];

这里的make.top.left.mas_equalTo(0); 就是一个链式操作,执行一个方法后的返回结果接着执行下一个方法,前边我们已经讲到RAC使用的是FPR编程思想,所以在RAC中你同样可以使用链式操作

我们修改一下上边的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
[[RACObserve(self, username)

filter:^(NSString *newName) {

return [newName hasPrefix:@"j"];

}]

subscribeNext:^(NSString *newName) {

NSLog(@"%@", newName);

}];

订阅:subscribeNext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

// When self.username changes, logs the new name to the console.

//

// RACObserve(self, username) creates a new RACSignal that sends the current

// value of self.username, then the new value whenever it changes.

// -subscribeNext: will execute the block whenever the signal sends a value.

[RACObserve(self, username) subscribeNext:^(NSString *newName) {

NSLog(@"%@", newName);

}];

当username内容发生变化,就会打印出一个新的值。

RACObserve(TARGET, KEYPATH) 是RAC提供的一个宏,他可以创建一个新的signal,这里,我们通过subscribeNext方法对 signal进行订阅,当username内容发生变化时,就会在block中获取username的新值并进行打印

bind 对信号进行绑定,返回一个新的信号,它会订阅原信号的值,在bindingBlock中对原信号的值进行转换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
RACSignal *orignSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { 

[subscriber sendNext:@1];

[subscriber sendCompleted];

return [RACDisposable disposableWithBlock:^{

NSLog(@"orign signal dispose");

}];

}];

RACSignal *newSignal = [orignSignal bind:^RACStreamBindBlock{

return ^(NSNumber *value, BOOL *stop){

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

[subscriber sendNext:@(value.integerValue * 2)];

[subscriber sendCompleted];

return [RACDisposable disposableWithBlock:^{

NSLog(@"bind dispose");

}];

}];

};

}];

[newSignal subscribeNext:^(id x) {

NSLog(@"newSignal value = %@", x);

}];

map:要完成对orign signal值得转换,使用map 和flattenMap是更简单的选择,这两个方法其实也是对bind方法的封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
RACSignal *orignSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { 

[subscriber sendNext:@1];

[subscriber sendCompleted];

return [RACDisposable disposableWithBlock:^{

NSLog(@"orign signal dispose");

}];

}];

[[orignSignal map:^id(NSNumber *value) {

return @(value.integerValue * 2);

}]subscribeNext:^(id x) {

NSLog(@"new value is %@", x);

}];

flattenMap 返回的是一个新的signal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
RACSignal *newSignal2 = [orignSignal flattenMap:^RACStream *(NSNumber * value) {

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

[subscriber sendNext:@(value.integerValue * 2)];

return nil;

}];

}];

[newSignal2 subscribeNext:^(id x) {

NSLog(@"new value2 is %@", x);

}];

filter:对seguence遍历后进行过滤,将不符合条件的数据进行过滤掉,返回一个新的sequence

nameArray.rac_sequence是将array转换为sequence,sequence代表了一个不可变的序列,它可以被订阅者订阅,而且还可以跟signal很方便的进行转换

1
2
3
4
5
6
7
8
9
NSArray *nameArray = @[@"tom", @"jerry", @"tomas", @"link"];

NSArray *resultArray = [nameArray.rac_sequence filter:^BOOL(NSString *name) {

return name.length > 3;

}].array;

NSLog(@"%@", resultArray);

combineLatest 使用一个signal数组,当数组中的任意一个signal值发生变化时,就在block中对所有signal最后一个值进行处理,最后返回一个新的signal。

1
2
3
4
5
self.validLoginSignal = [[RACSignal combineLatest:@[RACObserve(self, username), RACObserve(self, password)] reduce:^(NSString *username, NSString *password){

return @(username.isExist && password.isExist);

}] distinctUntilChanged];

zip 对多个信号的值进行压缩后创建一个RACTuples, zip将对每一个signal的值以配对的形式进行合并,比如signalA发送1和3,signal发送了2,那么合并后的Tuples包含了signal的1和signal的2。这里是zip和combineLatest最大的区别,在这里使用combineLatest会得到3和2,因为会重复利用signalB的旧值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { 

[subscriber sendNext:@1];

[subscriber sendNext:@3];

[subscriber sendCompleted];

return nil;

}];

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

[subscriber sendNext:@2];

[subscriber sendCompleted];

return nil;

}];

[[RACSignal zip:@[signalA, signalB]] subscribeNext:^(id x) {

NSLog(@"zip %@", x); //==>1,2

}];

[[RACSignal combineLatest:@[signalA, signalB]] subscribeNext:^(id x) {

NSLog(@"combineLatest: %@", x); //==>3,2

}];

merge

对多个signal进行合并,会监听到任意一个signal值得变化,并返回这个signal最新的值,当所有的signal发送complete时候会发送complate,当任意一个signal发送error立刻就发送error

1
2
3
4
5
[[RACSignal merge:@[signalA, signalB]] subscribeNext:^(id x) {

NSLog(@"x = %@", x);

}];