RACSignal 使用
// 1 創(chuàng)建信號
@weakify(self)
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
@strongify(self)
self.subsrcribe = subscriber;
// 3 發(fā)送信號
[subscriber sendNext:@"hahah"];
return [RACDisposable disposableWithBlock:^{
NSLog(@"銷毀了");
}];
}];
// 2 訂閱信號
[signal subscribeNext:^(id _Nullable x) {
// 第 3 步 發(fā)送信號后舶担, 此處 block 會被回調(diào)
NSLog(@"subscribeNext:%@",x);
}];
根據(jù)上述代碼流程想暗,RACSignal
的使用分別有 3 步
-
創(chuàng)建:實例一個
RACSignal
對象速蕊,并實現(xiàn)一個能夠獲取subscriber
訂閱者的block
-
訂閱:使用
RACSignal
對象進行訂閱滓侍,用于獲取發(fā)送信號后的回調(diào)結(jié)果 -
發(fā)送信號:使用
subscriber
訂閱者在特定位置發(fā)送信號(發(fā)送結(jié)果)顶伞,訂閱信號的block
獲取結(jié)果
一、RACSignal 的創(chuàng)建
以下我們開始分析一下 RACSignal
類型的對象是怎么來的
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
return [RACDisposable disposableWithBlock:^{
}];
}];
上述RACSignal
的創(chuàng)建 方法,
// 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);
// 創(chuàng)建 subscribe 對象 并保存 Next查近、Error、Completed 三個Block
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
// 傳入 subscribe 并創(chuàng)建 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];
上述方法雖然是在本類別里調(dià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 并創(chuàng)建 disposable册烈,
// 復(fù)合銷毀者
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
/**
* subscriber --- RACSubscriber
* signal --- self
* disposable
*/
// 新的(RACPassthroughSubscriber*)subscriber 擁有:disposable戈泼、signal、subscribe 三者合成
subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
// signal 有執(zhí)行 didsubscribe Block 往下走
if (self.didSubscribe != NULL) {
// 這里需要注意G牙濉0L竿稹次哈! 如果開啟了異步操作,RACScheduler.subscriptionScheduler 的類型是 “RACTargetQueueScheduler” 并在子線程執(zhí)行 【RACTargetQueueScheduler schedule:】
RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
// 這一步 self.didSubscribe(subscriber) 進行block 回調(diào)出去
RACDisposable *innerDisposable = self.didSubscribe(subscriber);
// 添加銷毀
[disposable addDisposable:innerDisposable];
}];
[disposable addDisposable:schedulingDisposable];
}
return disposable;
}
上述代碼我們主要看訂閱者subscriber
的回調(diào)流程:
// 只要外部執(zhí)行了
[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
// 這里得到 subscriber 的底層回調(diào)
}
當(dāng)?shù)讓邮褂?self.didSubscribe(subscribe) 就會回調(diào)出去上面的代碼塊里
小結(jié)一下整個訂閱過程主要做了的就是:
signal
訂閱了 subscribeNext:^(id _Nullable x)
的 block吆录,并內(nèi)部配置了 subscribe
窑滞,即:
subscriber->_next = [next copy];
subscriber->_error = [error copy];
subscriber->_completed = [completed copy];
此時 subscriber
擁有了下面 signal
的block 實現(xiàn)
// 三種訂閱原理都是一樣
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"subscribeNext:%@",x);
}];
[signal subscribeError:^(NSError * _Nullable error) {
NSLog(@"subscribeError");
}];
[signal subscribeCompleted:^{
NSLog(@"subscribeCompleted");
}];
下一步subscriber
就可以根據(jù)不同場景發(fā)送信號進行 block 回調(diào)了
三、 RACSignal 發(fā)送信號
使用subscriber
發(fā)送信號:
[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];
// 在回調(diào) block 之前 ,執(zhí)行了銷毀方法
[self.disposable dispose];
if (errorBlock == nil) return;
errorBlock(e);
}
}
- (void)sendCompleted {
@synchronized (self) {
void (^completedBlock)(void) = [self.completed copy];
// 在回調(diào) block 之前 哀卫,執(zhí)行了銷毀方法
[self.disposable dispose];
if (completedBlock == nil) return;
completedBlock();
}
}
上面 subscriber
根據(jù)不同方法分別調(diào)用了 nextBlock(value)巨坊,errorBlock(e),completedBlock()
使得第二步 signal
的訂閱信號得到了回調(diào)結(jié)果此改;
值得注意的是:
- (void)sendError:(NSError *)e
- (void)sendCompleted;
這兩個方法的實現(xiàn)里趾撵,分別都調(diào)用了
[self.disposable dispose];
這部操作把 subscriber
進行了銷毀, 之后的subscriber
如果再調(diào)用 sendNext, sendError , sendCompleted
或其他發(fā)送信號的方法共啃,都已經(jīng)失效了占调。
關(guān)于 RACSignal,RACSubscriber
就暫時介紹到這里,上述涉及到RACDisposable,RACScheduler
沒有作出過多的解釋移剪,后續(xù)抽時間會繼續(xù)寫下去究珊。
以上內(nèi)容純粹個人見解,僅用于分享交流纵苛;如有描述不當(dāng)之處剿涮,歡迎指出。