RACSignal 使用
// 1 创建信号
@weakify(self)
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
@strongify(self)
self.subsrcribe = subscriber;
// 3 发送信号
[subscriber sendNext:@"hahah"];
return [RACDisposable disposableWithBlock:^{
NSLog(@"销毁了");
}];
}];
// 2 订阅信号
[signal subscribeNext:^(id _Nullable x) {
// 第 3 步 发送信号后, 此处 block 会被回调
NSLog(@"subscribeNext:%@",x);
}];
根据上述代码流程,RACSignal
的使用分别有 3 步
-
创建:实例一个
RACSignal
对象,并实现一个能够获取subscriber
订阅者的block
-
订阅:使用
RACSignal
对象进行订阅,用于获取发送信号后的回调结果 -
发送信号:使用
subscriber
订阅者在特定位置发送信号(发送结果),订阅信号的block
获取结果
一、RACSignal 的创建
以下我们开始分析一下 RACSignal
类型的对象是怎么来的
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
return [RACDisposable disposableWithBlock:^{
}];
}];
上述RACSignal
的创建 方法,
// RACSignal.h
+ (RACSignal<ValueType> *)createSignal:
(RACDisposable * _Nullable (^)(id<RACSubscriber> subscriber))didSubscribe
// RACSignal.m
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
//RACDynamicSignal 继承于 RACSignal
return [RACDynamicSignal createSignal:didSubscribe];
}
因为返回的是 RACSignal
类型,却使用了
return [RACDynamicSignal createSignal:didSubscribe];
由此可得 RACDynamicSignal
这个子类做了一系列的实例化和包装处理,如下:
//RACDynamicSignal.m
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
// setNameWithFormat: 进行了一些列的底层打印日志操作,
// 最后还是返回了一个 RACSignal 的对象
return [signal setNameWithFormat:@"+createSignal:"];
}
二、RACSignal 订阅信号
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"subscribeNext:%@",x);
}];
上述方法是在 RACSignal (Subscription)
类别里的一个方法:
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
// 创建 subscribe 对象 并保存 Next、Error、Completed 三个Block
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
// 传入 subscribe 并创建 disposable
return [self subscribe:o];
}
RACSubscriber
的对象主要保存了 Next、Error、Completed
3个Block,再往里面跟一层如下:
// RACSubscriber.m
+ (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;
}
然后回到 上面的类别: RACSignal (Subscription)
return [self subscribe:o];
上述方法虽然是在本类别里调用
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
NSCAssert(NO, @"This method must be overridden by subclasses");
return nil;
}
但却被子类 RACDynamicSignal
重写了
// RACDynamicSignal.m
#pragma mark Managing Subscribers
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
NSCParameterAssert(subscriber != nil);
// 传入 subscribe 并创建 disposable,
// 复合销毁者
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
/**
* subscriber --- RACSubscriber
* signal --- self
* disposable
*/
// 新的(RACPassthroughSubscriber*)subscriber 拥有:disposable、signal、subscribe 三者合成
subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
// signal 有执行 didsubscribe Block 往下走
if (self.didSubscribe != NULL) {
// 这里需要注意!!!! 如果开启了异步操作,RACScheduler.subscriptionScheduler 的类型是 “RACTargetQueueScheduler” 并在子线程执行 【RACTargetQueueScheduler schedule:】
RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
// 这一步 self.didSubscribe(subscriber) 进行block 回调出去
RACDisposable *innerDisposable = self.didSubscribe(subscriber);
// 添加销毁
[disposable addDisposable:innerDisposable];
}];
[disposable addDisposable:schedulingDisposable];
}
return disposable;
}
上述代码我们主要看订阅者subscriber
的回调流程:
// 只要外部执行了
[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
// 这里得到 subscriber 的底层回调
}
当底层使用 self.didSubscribe(subscribe) 就会回调出去上面的代码块里
小结一下整个订阅过程主要做了的就是:
signal
订阅了 subscribeNext:^(id _Nullable x)
的 block,并内部配置了 subscribe
,即:
subscriber->_next = [next copy];
subscriber->_error = [error copy];
subscriber->_completed = [completed copy];
此时 subscriber
拥有了下面 signal
的block 实现
// 三种订阅原理都是一样
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"subscribeNext:%@",x);
}];
[signal subscribeError:^(NSError * _Nullable error) {
NSLog(@"subscribeError");
}];
[signal subscribeCompleted:^{
NSLog(@"subscribeCompleted");
}];
下一步subscriber
就可以根据不同场景发送信号进行 block 回调了
三、 RACSignal 发送信号
使用subscriber
发送信号:
[subscriber sendNext:@"hahah"];
[subscriber sendError:nil];
[subscriber sendCompleted];
// RACSubscriber.m
#pragma mark RACSubscriber
- (void)sendNext:(id)value {
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
nextBlock(value);
}
}
- (void)sendError:(NSError *)e {
@synchronized (self) {
void (^errorBlock)(NSError *) = [self.error copy];
// 在回调 block 之前 ,执行了销毁方法
[self.disposable dispose];
if (errorBlock == nil) return;
errorBlock(e);
}
}
- (void)sendCompleted {
@synchronized (self) {
void (^completedBlock)(void) = [self.completed copy];
// 在回调 block 之前 ,执行了销毁方法
[self.disposable dispose];
if (completedBlock == nil) return;
completedBlock();
}
}
上面 subscriber
根据不同方法分别调用了 nextBlock(value),errorBlock(e),completedBlock()
使得第二步 signal
的订阅信号得到了回调结果;
值得注意的是:
- (void)sendError:(NSError *)e
- (void)sendCompleted;
这两个方法的实现里,分别都调用了
[self.disposable dispose];
这部操作把 subscriber
进行了销毁, 之后的subscriber
如果再调用 sendNext, sendError , sendCompleted
或其他发送信号的方法,都已经失效了。
关于 RACSignal,RACSubscriber
就暂时介绍到这里,上述涉及到RACDisposable,RACScheduler
没有作出过多的解释,后续抽时间会继续写下去。
以上内容纯粹个人见解,仅用于分享交流;如有描述不当之处,欢迎指出。