ReactiveObjC (一)
RAC 框架中的主要类
RACSignal
信号类,一般表示将数据传递,只要有数据改变,信号内部就接收到数据,马上发出数据。
-
RACSignal 本身并不具备发送信号的能力,而是交给内部一个订阅者发出。
-
默认一个信号都是冷信号,也就是值改变了,也不会触发,只有订阅了这个信号,这个信号才会变成热信号,值改变才会触发。
-
调用信号 RACSingal 的subscribeNext 就能订阅
#1.创建订阅者
RACSignal * signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
#3.发送信号,发送信号之前一定要先订阅信号
每当有订阅者订阅信号,就会调用block。
[subscriber sendNext:@"1"];
#如果不在发送数据,最好发送信号完成,
内部会自动调用[RACDisposable disposable]取消订阅信号
[subscriber sendCompleted];
# 当信号发送完成或者发送错误,就会自动执行这个block,取消订阅信号
return [RACDisposable disposableWithBlock:^{
# 执行完Block后,当前信号就不在被订阅了。
NSLog(@"信号被销毁");
}];
}];
#2. 订阅信号,才会激活信号
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"--%@", x);
}];
分析:
-
创建信号方法内部会创建 RACDynamicSignal ,
并持有:^RACDisposable *(id<RACSubscriber> _Nonnull subscriber)。 -
当订阅信号方法subscribeNext执行时,内部会创建一个RACSubscriber对象且持有nextBlock。
进而做为参数,调用创建信号的Block。 -
subscriber 调用 sendNext 方法时,会调用它的nextBlock方法
所以RACSignal的处理流程就是
创建信号的block会在订阅信号的时候调用
订阅信号的block会在订阅者发布信息的时候调用
RACSubject
信号提供者,自己可以充当信号,又能发送信息。
一般用来代替代理 需要先订阅
#1.创建信号
<创建数组,在信号对象中>
RACSubject *subject = [RACSubject subject];
#2.订阅信号
<创建订阅者,将block 保存在订阅者中,将订阅者放在上面的数组中>
[subject subscribeNext:^(id x) {
// block调用时刻:当信号发出新值,就会调用.
NSLog(@"第一个订阅者%@",x);
}];
#3.发送信号
<遍历信号对象中的数组,取出订阅者对象,调用订阅者对旬中的Block>
[subject sendNext:@"1"];
[subject subscribeNext:^(id x) {
// block调用时刻:当信号发出新值,就会调用.
NSLog(@"第二个订阅者%@",x);
}];
分析:
遍历信号对象中的数组,取出订阅者对象,调用订阅者对旬中的Block
只有第一个订阅者能订阅到1
RACReplaySubject
RACSubject的子类,重复提供信号类,可以先订阅信号,也可以先发送信号
如果一个信号每被订阅一次,就需要把之前的值重复发送一遍,使用重复提供信号类。
RACReplaySubject创建方法
1.创建RACSubject
2.订阅信号
3.发送信号
工作流程:
1. 订阅信号,内部保存了订阅者,和订阅者相应的block
2. 当发送信号的,遍历订阅者,调用订阅者的nextBlock
3. 发送的信号会保存起来,当订阅者订阅信号的时候,会将之前保存的信号,
一个个作用于新的订阅者,保存信号的容量由capacity决定,这也是有别于RACSubject的
#1.创建信号
RACReplaySubject *replaySubject = [RACReplaySubject subject];
# 2.发送信号
[replaySubject sendNext:@1];
[replaySubject sendNext:@2];
# 3.订阅信号
[replaySubject subscribeNext:^(id x) {
NSLog(@"第一个订阅者接收到的数据%@",x);
}];
// 订阅信号
[replaySubject subscribeNext:^(id x) {
NSLog(@"第二个订阅者接收到的数据%@",x);
}];
//先发送后订阅
第一个订阅者接收到的数据1
第一个订阅者接收到的数据2
第二个订阅者接收到的数据1
第二个订阅者接收到的数据2
# 1.创建信号
RACReplaySubject *replaySubject = [RACReplaySubject subject];
# 2.订阅信号
[replaySubject subscribeNext:^(id x) {
NSLog(@"第一个订阅者接收到的数据%@",x);
}];
// 订阅信号
[replaySubject subscribeNext:^(id x) {
NSLog(@"第二个订阅者接收到的数据%@",x);
}];
#3.发送信号
[replaySubject sendNext:@1];
[replaySubject sendNext:@2];
//先订阅后发送
第一个订阅者接收到的数据1
第二个订阅者接收到的数据1
第一个订阅者接收到的数据2
第二个订阅者接收到的数据2
-(void)RACReplaySubject{
RACReplaySubject *replaySubject = [RACReplaySubject subject];
[replaySubject subscribeNext:^(id x) {
NSLog(@" 1 %@",x);
}];
[replaySubject subscribeNext:^(id x) {
NSLog(@"2 %@",x);
}];
[replaySubject sendNext:@7];
[replaySubject sendNext:@6];
[replaySubject subscribeNext:^(id x) {
NSLog(@"3 %@",x);
}];
2021-03-02 18:38:48.556649+0800 **[14580:4162497] 1 7
2021-03-02 18:38:48.556783+0800 **[14580:4162497] 2 7
2021-03-02 18:38:48.556951+0800 **[14580:4162497] 1 6
2021-03-02 18:38:48.557089+0800 **[14580:4162497] 2 6
2021-03-02 18:38:48.557242+0800 **[14580:4162497] 3 7
2021-03-02 18:38:48.557348+0800 **[14580:4162497] 3 6
}
RACCommand
RAC中用于处理事件的类,可以把事件如何处理,事件中的数据如何传递,包装到这个类中,他可以很方便的监控事件的执行过程。
#1.创建命令
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
NSLog(@"执行命令");
# 创建空信号,必须返回信号,不能返回nil,可以返回空信号
//return [RACSignal empty];
#2.创建信号,用来传递数据
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"请求数据"];
#数据传递完,最好调用sendCompleted,这时命令才执行完毕。
[subscriber sendCompleted];
return nil;
}];
}];
#3.订阅RACCommand中的信号
[[command execute:nil] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
监听命令执行过程
#监听命令是否执行完毕,默认会来一次,可以直接跳过,skip表示跳过第一次信号。
[[command.executing skip:1] subscribeNext:^(id x) {
if ([x boolValue] == YES) {
// 正在执行
NSLog(@"正在执行");
}else{
// 执行完成
NSLog(@"执行完成");
}
}];
// 执行命令
[self.conmmand execute:@1];