简介
ReactiveObjc将原有的各种设计模式,包括代理、Target/Action、block、通知中心以及观察者模式各种『输入』,都抽象成了数据流或者信号(也可以理解为状态流)让单一的组件能够对自己的响应动作进行控制,简化了视图控制器的负担。ReactiveObjc整个框架主要是围绕Signal来运转。
我们先来看一段代码
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
return [RACDisposable disposableWithBlock:^{
NSLog(@"释放");
}];
}];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
这段代码的打印
2021-04-12 15:15:31.988297+0800 ZLXStudyDemo[64724:7390883] 1
2021-04-12 15:15:31.988485+0800 ZLXStudyDemo[64724:7390883] 2
2021-04-12 15:15:31.988587+0800 ZLXStudyDemo[64724:7390883] 3
2021-04-12 15:15:34.694916+0800 ZLXStudyDemo[64724:7390883] 释放
这段代码包含ReactiveObjc的信号完成使用逻辑。
我们先大致分析下:通过RACSignal的createSignal:创建一个signal->signal通过subscribeNext:订阅一个信号-> RACSubscriber通过sendNext来触发订阅的信号。
下面我们从以下四方来解析上述过程的原理:
- 信号的创建
- 信号的订阅
- 订阅的响应
- 订阅的回收
信号的创建
RACSignal是ReactiveObjc框架信号处理的核心。信号的创建我们主要来看下这个类。
先看下创建相关的代码:
// step1
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
return [RACDisposable disposableWithBlock:^{
NSLog(@"释放");
}];
}];
// step2
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
return [RACDynamicSignal createSignal:didSubscribe];
}
//step3
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
}
信号的创建是不是非常简单。
- RACSignal调用create内部再调用RACDynamicSignal的create
-
RACDynamicSignal将传入Subscribeblock绑定到RACDynamicSignal的didSubscribe属性上。
image.png
所以整个信号的订阅我们可以理解为:绑定信号关联的block到RACDynamicSignal的didSubscribe属性上。
这个关联的block什么时候触发呢? 怎么触发的呢? 接下来我们来看下信号的订阅。
信号的订阅
ReactiveObjc订阅的相关逻辑我们主要看RACSubscriber
订阅相关的代码:
// step1
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// step2
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}
//step3
+ (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed {
RACSubscriber *subscriber = [[self alloc] init];
subscriber->_next = [next copy];
subscriber->_error = [error copy];
subscriber->_completed = [completed copy];
return subscriber;
}
//step4
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
NSCParameterAssert(subscriber != nil);
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
if (self.didSubscribe != NULL) {
RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
RACDisposable *innerDisposable = self.didSubscribe(subscriber);
[disposable addDisposable:innerDisposable];
}];
[disposable addDisposable:schedulingDisposable];
}
return disposable;
}
我们来分析下订阅的过程:
- RACSignal调用订阅API,传入订阅的block
- 创建RACSubscriber,并绑定上一步的block
- RACSignal调用subscribe,传入上一步创建的RACSubscriber,
- 调用之前RACSignal信号创建时候绑定的didSubscribe,并传入上一步传入的RACSubscriber
让我们在看看看刚开始的代码,现在知道[subscriber sendNext:@"1"];这个subscriber是什么时候创建的了吗?上面的步骤2
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
// 这个subscriber什么时候创建的呢?
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
return [RACDisposable disposableWithBlock:^{
NSLog(@"释放");
}];
}];
订阅的响应
//step1 调用sendNext
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
return [RACDisposable disposableWithBlock:^{
NSLog(@"释放");
}];
}];
//step2 调用nextBlock
- (void)sendNext:(id)value {
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
nextBlock(value);
}
}
// 响应block
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
这个流程是不是很简单。给你个问题 nextblock哪里来的?
订阅的取消
RACDisposable 是订阅回收的核心。主要思想是用来处理异步的操作。
每一个异步操作关联一个RACDisposable,当执行操作的时候,去check RACDisposable的状态。
我们来看下之前的订阅代码
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
NSCParameterAssert(subscriber != nil);
//step1 创建一个容器disposable,可以同时处理多个disposable
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
//消息转发。主要作用是check disposable状态
subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
if (self.didSubscribe != NULL) {
//step2
RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
RACDisposable *innerDisposable = self.didSubscribe(subscriber);
//step3
[disposable addDisposable:innerDisposable];
}];
//step4
[disposable addDisposable:schedulingDisposable];
}
return disposable;
}
我们来看下代码吧,每次执行操作的时候都去check下disposed。
- (RACDisposable *)schedule:(void (^)(void))block {
NSCParameterAssert(block != NULL);
RACDisposable *disposable = [[RACDisposable alloc] init];
dispatch_async(self.queue, ^{
if (disposable.disposed) return;
[self performAsCurrentScheduler:block];
});
return disposable;
}
// RACSubscriber 释放调用挂载的RACDisposable的block
- (void)dealloc {
[self.disposable dispose];
}