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