文章系列
《RACSignal 》
《RACDisposable》
《RACSubject、RACReplaySubject》
《iOS RAC - 基本用法》
《iOS RAC - 定時(shí)器》
《iOS RAC - RACMulticastConnection》
《iOS RAC - RACCommand》
《iOS RAC - 核心方法bind》
《iOS RAC - 集合RACTuple、RACSequence》
《iOS RAC - rac_leftSelector》
《iOS RAC - 映射》
《iOS RAC - 過濾》
《iOS RAC - 登錄頁面,MVVM》
- 項(xiàng)目中如果沒有使用swift的話使用cocoapods 導(dǎo)入
pod ‘ReactiveObjC’, ‘~> 3.0.0’
然后在導(dǎo)入頭文件ReactiveObjC.h
就可以使用了,3.0.0
以上的版本支持了swift,如果你是純OC工程,不建議使用3.0.0
以上的版本。
RACSignal:顧名思義,信號(hào)類,signal本身不具備發(fā)送信號(hào)的能力,下面通過代碼來看看。
在創(chuàng)建RACSignal中先說一下RAC的三部曲
- 1 創(chuàng)建信號(hào)
- 2 訂閱信號(hào)
- 3 發(fā)送信息
//1、創(chuàng)建信號(hào)量
RACSignal * signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"創(chuàng)建信號(hào)量");
//3、發(fā)布信息
[subscriber sendNext:@"I'm send next data"];
NSLog(@"那我啥時(shí)候運(yùn)行");
return nil;
}];
//2、訂閱信號(hào)量
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
代碼分析 - 創(chuàng)建信號(hào)
[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
return nil;
}];
這里要?jiǎng)?chuàng)建一個(gè)Signal對(duì)象,然后它馬上給我一個(gè)block,
并且在block中要返回一個(gè)RACDisposable
對(duì)象,
剛開始接觸RAC的我哪里知道這個(gè)是什么鬼,直接返回nil
至此我們完成了第一步,創(chuàng)建信號(hào)
然后其內(nèi)部實(shí)現(xiàn)我們并不了解,于是我們點(diǎn)擊進(jìn)去看看其內(nèi)部如何實(shí)現(xiàn)的。
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
return [RACDynamicSignal createSignal:didSubscribe];
}
可以看到其內(nèi)部創(chuàng)建了一個(gè)RACDynamicSignal
信號(hào),并且把didSubscribe
這個(gè)block也傳過去了,然后在點(diǎn)進(jìn)去看看
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
}
這段代碼意思就很清楚了,創(chuàng)建一個(gè)RACDynamicSignal
,保存didSubscribe
這個(gè)block,返回RACDynamicSignal
這個(gè)對(duì)象。
通過上面的了解,我們可以知道,創(chuàng)建信號(hào)這個(gè)方法內(nèi)部會(huì)幫我們創(chuàng)建一個(gè)RACDynamicSignal
并且保存一個(gè)didSubscribe
block。
但是這個(gè)block什么時(shí)候調(diào)用呢?
沒錯(cuò)就是在我們訂閱信號(hào)的時(shí)候調(diào)用
代碼分析 - 訂閱信號(hào)
//2、訂閱信號(hào)量
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
這里一訂閱信號(hào)就給我一個(gè)block,并且還帶一個(gè)參數(shù)x,并不知道是餓什么東西,就先打印出來。
然后我們點(diǎn)擊進(jìn)去看下內(nèi)部實(shí)現(xiàn)
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}
- 1、創(chuàng)建一個(gè)訂閱者
+ (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;
}
保存了nextblock
- 2、 調(diào)用
subscribe
方法
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
NSCParameterAssert(subscriber != nil);
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
//這里判斷didSubcribe是否為空
if (self.didSubscribe != NULL) {
RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
//這里就在調(diào)用didSubscribe方法,并且把剛才傳入的subscriber調(diào)用出去
RACDisposable *innerDisposable = self.didSubscribe(subscriber);
[disposable addDisposable:innerDisposable];
}];
[disposable addDisposable:schedulingDisposable];
}
return disposable;
}
在這個(gè)方法中會(huì)判斷是有有didSubscriber,
如果有就調(diào)用block并且把傳入進(jìn)來的subscriber作為block的參數(shù)調(diào)用出去
訂閱信號(hào)之后就會(huì)運(yùn)行創(chuàng)建信號(hào)的block,
這個(gè)時(shí)候我們再來看下創(chuàng)建信號(hào)的方法
[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
NSLog(@"創(chuàng)建信號(hào)量");
//3、發(fā)布信息
[subscriber sendNext:@"I'm send next data"];
NSLog(@"那我啥時(shí)候運(yùn)行");
return nil;
}];
//2、訂閱信號(hào)量
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
它給我們一個(gè)subscriber
而這個(gè)sbuscriber就是我們調(diào)用訂閱信號(hào)的方法所創(chuàng)建的subscriber,然后我們要用這個(gè)訂閱者發(fā)送信息
那我們訂閱的信號(hào)啥時(shí)候調(diào)用呢?
- 當(dāng)我們的訂閱者發(fā)送消息的時(shí)候就會(huì)調(diào)用。
這個(gè)時(shí)候我們看下訂閱者發(fā)送信息的方法內(nèi)部做了什么
- (void)sendNext:(id)value {
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
nextBlock(value);
}
}
這里的代碼很簡潔了 主要就是做了一件事,如果nextblock不為空就把傳進(jìn)來傳value原封不動(dòng)的調(diào)用出去。 而這個(gè)nextblock就是我們在訂閱信號(hào)的時(shí)候創(chuàng)建的那個(gè)subscriber所保存的nextblock。
所以RACSignal的處理流程就是
- 創(chuàng)建信號(hào)的block會(huì)在訂閱信號(hào)的時(shí)候調(diào)用
- 訂閱信號(hào)的block會(huì)在訂閱者發(fā)布信息的時(shí)候調(diào)用
流程圖