1.ReactiveCocoa 常见操作方法介绍
1.1 ReactiveCocoa操作须知
- 所有信号(RACSignal)都可以进行操作处理, 因为所有操作都定义在RACStream.h中,而RACSignal继承RACStream.
1.2 ReactiveCocoa操作思想
- 运用的是Hook思想, Hook是一种用于改变API执行结果的技术.
- Hook的用处: 截获API调用的技术
- Hook的原理: 在每次调用一个API返回结果之前, 先执行自己的方法, 改变结果的输出
- RAC开发方式: RAC中核心开发方式, 也是
绑定
. 以前的开发方式是赋值
, 而用RAC开发应该把重心放在绑定
, 也就是说可以在创建一个对象的时候, 就绑定好以后想要做的事情, 而不是等赋值以后再去做事情 - 例如: 把数据展示到控件上, 之前都是重写控件的setModel方法, 用RAC就可以在一开始创建控件的时候, 就绑定好数据.
1.3 ReactiveCocoa核心方法 Bind
接受到信号后, 可以做中间处理再返回数据
// 1,绑定信号
RACSubject *subject = [RACSubject subject];
// 2,绑定信号
RACSignal *bindSignal = [subject bind:^RACStreamBindBlock{
return ^RACSignal *(id value, BOOL *stop){
// block调用: 只要源信号发送数据, 就会调用block
// block作用: 处理源信号内容
// value: 源信号发送的内容
NSLog(@"接收到的原信号的内容:%@",value);
value = [NSString stringWithFormat:@"<经过处理的原信号:%@>",value];
return [RACReturnSignal return:value];
};
}];
// 3,订阅绑定信号
[bindSignal subscribeNext:^(id x) {
NSLog(@"接受绑定信号内容:%@",x);
}];
// 4,发送信号
[subject sendNext:@"100"];
打印的内容
接收到的原信号的内容:100
接受绑定信号内容:<经过处理的原信号:100>
1.4 ReactiveCocoa操作方法 - 映射(flattenMap, Map)
- flattenMap简单用法, 可以看到, flattenMap方法中, 返回值通过一个信号来返回,
RACSubject *subject = [RACSubject subject];
RACSignal *bindSignal = [subject flattenMap:^RACStream *(id value) {
NSString *fixStr = [NSString stringWithFormat:@"RR : %@",value];
return [RACReturnSignal return:fixStr];
}];
[bindSignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[subject sendNext:@"Jason"];
- Map的简单使用, Map就是flattenMap的一个简化版本,也更实用一些,使用Map后返回一个新的bind信号, 订阅新的绑定信号, 接收到的订阅信息就是map处理后的信息了.
RACSubject *subject = [RACSubject subject];
RACSignal *bindSignal = [subject map:^id(id value) {
return [NSString stringWithFormat:@"RR : %@",value];
}];
[bindSignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[subject sendNext:@"Jason"];
1.5 ReactiveCocoa操作方法 - 组合
- concat: 按一定顺序拼接信号, 当多个信号发出的时候, 有顺序的接受信号.
皇帝 和 太子的关系, 皇帝驾崩了皇太子才能继位.
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@0];
// 如果不设置订阅者已发送完成, 那么concatSignal不会接收到,信号B发送出的信号.
//[subscriber sendCompleted];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1110];
return nil;
}];
// 把signalA 拼接到signalB后, signalA发送完成, signalB才会被激活
RACSignal *concatSignal = [signalA concat:signalB];
// 以后只需要面对拼接信号开发
// 订阅拼接的信号, 不需要单独订阅signalA,signalB
// 内部会自动订阅
// 注意: 第一个信号必须发送完成,第二个信号才会被激活
[concatSignal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
-
then: 用于连接两个信号, 当第一个信号完成, 才会连接then返回的信号
then的用法和concat很相似, 也更简化.下面用响应式写法实现.
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@0];
[subscriber sendCompleted];
return nil;
}] then:^RACSignal *{
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@100];
return nil;
}];
}] subscribeNext:^(id x) {
// 只能接收到第二个信号的值, 也就是then返回信号的值.
NSLog(@"%@",x);
}];
- merge: 把多个信号合并为一个信号, 任何一个信号有新值的时候就会调用.
RACSubject *signalA = [RACSubject subject];
RACSubject *signalB = [RACSubject subject];
RACSignal *mergeSignal = [signalA merge:signalB];
[mergeSignal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
[signalB sendNext:@"信号B"];
[signalA sendNext:@"信号A"];
打印信息:
信号B
信号A
底层实现:
1,合并信号被订阅的时候, 就会遍历所有信号, 并发出这些信号
2,每发出一个信号, 这个信号就会被订阅
3,也就是合并信号一被订阅, 就会订阅里面所有的信号
4,只要有一个信号被发出就会被监听.
- zipWith: 把两个信号压缩成一个信号, 只有当 两个信号 同时发出信号内容时, 并且两个信号的内容合并成一个元组, 才会触发压缩流的next事件
夫妻关系-> 内容需要都完成,才能出发之后的事情.
RACSubject *signalA = [RACSubject subject];
RACSubject *signalB = [RACSubject subject];
RACSignal *zipSignal = [signalA zipWith:signalB];
[zipSignal subscribeNext:^(id x) {
// x的类型的RACTuple
// 其中内容的顺序是压缩时放入的顺序,
NSLog(@"%@", x);
}];
// 需压缩的信号均发送信号, 订阅者才会接收到消息.
[signalB sendNext:@"B"];
[signalA sendNext:@"A"];
- 底层实现
1,定义压缩信号, 内部就会自动订阅signalA, signalB
2.每当signalA或者signalB发出信号,就会判断signalA,signalB有没有发出个信号,有就会把最近发出的信号都包装成元组发出。
-
combineLatestWith: 将两个信号合并起来, 并且拿到各个信号的最新值, 必须每个合并的signal至少都有过一次sendNext, 才会触发合并的信号, 一般和
reduce
一起使用. -
combineLatest (此方法为类方法) 合并多个信号,并且拿到各个信号的最新值, 必须每个合并的signal至少都有过一次sendNext, 才会触发合并的信号, 一般和
reduce
一起使用.
RACSubject *signalA = [RACSubject subject];
RACSubject *signalB = [RACSubject subject];
RACSubject *signalC = [RACSubject subject];
RACSubject *signalD = [RACSubject subject];
// reduce 的参数列表和
[[RACSignal combineLatest:@[signalA ,signalB, signalC, signalD] reduce:^id(NSString *sA,NSString *sB,NSString *sC,NSString *sD){
NSLog(@"%@%@%@%@",sA,sB,sC,sD);
return @1;
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[signalA sendNext:@"A"];
[signalB sendNext:@"B"];
[signalC sendNext:@"C"];
[signalD sendNext:@"D"];
1.6 ReactiveCocoa操作方法 - 过滤
-
filter
:过滤信号, 使用它可以获取满足条件的信号.
[self.textField.rac_textSignal filter:^BOOL(NSString *value) {
return value.length > 3;
}];
-
ignore
:忽略某些值的信号. 是filter的一种实现
[[self.textField.rac_textSignal ignore:@"1"] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
-
distinctUntilChanged
:当上一次的值和当前的值有变化就会发出信号, 否则被忽略
// 过滤, 当上一次和当前值不一样,就会发出内容
// 开发中, 刷新UI经常使用, 只有两次数据不一样才需要刷新
[[self.textField.rac_textSignal distinctUntilChanged] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
-
take
:从开始一共去N次信号
// 1,创建信号
RACSubject *signal = [RACSubject subject];
// 2,处理信号, 订阅信号
[[signal take:1] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 3,发送信号
[signal sendNext:@1];
[signal sendNext:@2]; // 这次发送的内容,就不会接受到了.
-
takeLast
:取最后N次的信号, 前提条件是,订阅者必须完成sendCompleted, 之后完成才知道一共有多少条信号发送
// 1,创建信号
RACSubject *signal = [RACSubject subject];
// 2,处理信号, 订阅信号
[[signal takeLast:2] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 3,发送信号
[signal sendNext:@1];
[signal sendNext:@2];
[signal sendNext:@3];
[signal sendNext:@4];
[signal sendCompleted];
-
takeUntil
:只要传入的信号发送完成或者发送任何数据, 那么就不会接受原信号发送的内容
// 1,创建信号
RACSubject *subject = [RACSubject subject];
RACSubject *signal = [RACSubject subject];
// 2,处理信号, 订阅信号
[[subject takeUntil:signal] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 3,发送信号
[subject sendNext:@1];
[subject sendNext:@2];
[signal sendCompleted];
// [signal sendNext:@2];
// [signal sendError:nil]; // 发送error不会阻止原信号.
[subject sendNext:@3];
[subject sendNext:@4];
[subject sendCompleted];
-
skip
:(NSUInteger):跳过几个信号,不接受。
// 1,创建信号
RACSubject *subject = [RACSubject subject];
// 2,处理信号, 订阅信号
[[subject skip:2] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 3,发送信号
[subject sendNext:@1];
[subject sendNext:@2];
[subject sendNext:@3];
[subject sendNext:@4];
-
switchToLatest
:用于signalOfSignals(信号的信号),有时候信号也会发出信号,会在signalOfSignals中,获取signalOfSignals发送的最新信号。
RACSubject *signalOfSignals = [RACSubject subject];
RACSubject *signal = [RACSubject subject];
// 获取信号中信号最近发出信号,订阅最近发出的信号。
// 注意switchToLatest:只能用于信号中的信号
[signalOfSignals.switchToLatest subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[signalOfSignals sendNext:signal];
[signal sendNext:@1];
网友评论