1、ReactiveCocoa开发中常见用法
-
代替代理:
rac_signalForSelector:用于替代代理。
-
代替KVO :
rac_valuesAndChangesForKeyPath:用于监听某个对象的属性改变。
-
监听事件:
rac_signalForControlEvents:用于监听某个事件。
-
代替通知:
rac_addObserverForName:用于监听某个通知。
-
监听文本框文字改变:
rac_textSignal:只要文本框发出改变就会发出这个信号。
2、ReactiveCocoa高级用法
-
Map
Map作用:把源信号的值映射成一个新的值
###### Map使用步骤:
1.传入一个block,类型是返回对象,参数是value
2.value就是源信号的内容,直接拿到源信号的内容做处理
3.把处理好的内容,直接返回就好了,不用包装成信号,返回的值,就是映射的值。
Map使用场景:
1.服务端返回的数据不是你需要的,需要进行一次二次加工,使用 map就会很方便
[[_textField.rac_textSignal map:^id(id value) {
// 当源信号发出,就会调用这个block,修改源信号的内容
// 返回值:就是处理完源信号的内容。
return [NSString stringWithFormat:@"输出:%@",value];
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
-
concat
concat:按一定顺序拼接信号,当多个信号发出的时候,有顺序的接收信号。
concat使用场景:
1.在工作中,有这样的需求,可能一个页面要发送几个API,要求有一个API是依赖其他几个API,等到所有API都成功之后在刷新UI
RACSignal *signal1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signal2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@2];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signal3 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"3"];
[subscriber sendCompleted];
return nil;
}];
//信号3依赖信号1和信号2
RACSignal *signal = [[[RACSignal merge:@[signal1,signal2]]concat:signal3] filter:^BOOL(id value) {
return [value isKindOfClass:[NSNumber class]];
}];
[signal subscribeNext:^(id x) {
NSLog(@"====%@",x);
}completed:^{
NSLog(@"所有都完事了");
}];
log
2017-03-07 17:25:35.339 racDemo[61024:1544009] ====1
2017-03-07 17:25:35.340 racDemo[61024:1544009] ====2
2017-03-07 17:25:35.341 racDemo[61024:1544009] 所有都完事了
记得加 [subscriber sendCompleted];
-
Zip
zip:把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,并且把两个信号的内容合并成一个元组,才会触发压缩流的next事件。
RACSignal *signal1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signal2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@2];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signal3 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"3"];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signal = [RACSignal zip:@[signal1,signal2,signal3] reduce:^id(NSNumber *s1,NSNumber *s2,NSString *s3){
return RACTuplePack(s1,s2,s3);
}];
[signal subscribeNext:^(RACTuple *tuple) {
RACTupleUnpack(NSNumber *num1,NSNumber *num2,NSString *s3) = tuple;
NSLog(@"%@%@%@",num1,num2,s3);
}completed:^{
NSLog(@"所有都完事了");
}];
log
2017-03-07 17:38:57.227 racDemo[61197:1553408] 123
2017-03-07 17:38:57.227 racDemo[61197:1553408] 所有都完事了
tips:
1,记住要发送 [subscriber sendCompleted];
2,顺序不要乱了,每一个信号对应一个返回,顺序错了,返回的值也就不对应了
3,sendNext只会走一次,如果有两个sendNext,那么第二个发过来的值就不会生效
4,如果只要一个值,就没有必要RACTuplePack了
eg:
[subscriber sendNext:@"3"];
[subscriber sendNext:@"100"];
[subscriber sendCompleted];
同样代码,在后面多加上一个sendNext 输出结果如下
2017-03-07 17:44:17.808 racDemo[61350:1558976] 123
2017-03-07 17:44:17.808 racDemo[61350:1558976] 所有都完事了
-
combineLatest:
combineLatest将多个信号合并起来,并且拿到各个信号的最新的值,必须每个合并的signal至少都有过一次sendNext,才会触发合并的信号。
RACSignal combineLatest:<#(id<NSFastEnumeration>)#> reduce:<#^id(void)reduceBlock#>
RACSignal combineLatest:<#(id<NSFastEnumeration>)#>
用法和zip reduce差不多,但是每次有最新的都会回调
-
filter:
// 过滤:
// 每次信号发出,会先执行过滤条件判断.
[_textField.rac_textSignal filter:^BOOL(NSString *value) {
return value.length > 3;
}];
-
doNext && doCompleted
[[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}] doNext:^(id x) {
// 执行[subscriber sendNext:@1];之前会调用这个Block
NSLog(@"doNext");;
}] doCompleted:^{
// 执行[subscriber sendCompleted];之前会调用这个Block
NSLog(@"doCompleted");;
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
-
interval
[[RACSignal interval:1 onScheduler:[RACScheduler currentScheduler]] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
-
then
then:用于连接两个信号,当第一个信号完成,才会连接then返回的信号。
// then:用于连接两个信号,当第一个信号完成,才会连接then返回的信号
// 注意使用then,之前信号的值会被忽略掉.
// 底层实现:1、先过滤掉之前的信号发出的值。2.使用concat连接then返回的信号
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}] then:^RACSignal *{
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@2];
return nil;
}];
}] subscribeNext:^(id x) {
// 只能接收到第二个信号的值,也就是then返回信号的值
NSLog(@"%@",x);
}];