上一篇介紹了一下RAC訂閱信號(hào)中晴音,方法實(shí)現(xiàn)RACCompoundDisposable真正的訂閱者類的相關(guān)介紹灰粮。
這一篇炬搭,將在訂閱信號(hào)的方法中繼續(xù)探究夺姑,當(dāng)真正的訂閱者初始化之后墩邀,后續(xù)代碼涉及到了RACScheduler類的使用。將針對(duì)RACScheduler類進(jìn)行深入的剖析盏浙。
先從上圖的代碼中可以發(fā)現(xiàn)眉睹,RACScheduler的block代碼塊中,有執(zhí)行self.didSubscribe( )代碼塊的代碼废膘,即執(zhí)行創(chuàng)建信號(hào)時(shí)的代碼塊竹海,也就意味著此處的schedule代碼塊是必須執(zhí)行。
跳轉(zhuǎn)進(jìn)入查看schedule方法殖卑,可以發(fā)現(xiàn)有多個(gè)基于RACScheduler的子類站削,都有該實(shí)現(xiàn)方法坊萝。
在RACScheduler類中孵稽,有三種子類:RACImmediateScheduler、RACSubscriptionScheduler和RACQueueScheduler
在RACImmediateScheduler子類看到schedule方法中十偶,是立即執(zhí)行block代碼塊菩鲜。
- (RACDisposable *)schedule:(void (^)(void))block {
NSCParameterAssert(block != NULL);
block();
return nil;
}
接著是RACSubscriptionScheduler子類中的schedule方法實(shí)現(xiàn)。
- (RACDisposable *)schedule:(void (^)(void))block {
NSCParameterAssert(block != NULL);
if (RACScheduler.currentScheduler == nil) return [self.backgroundScheduler schedule:block];
block();
return nil;
}
在RACSubscriptionScheduler子類schedule方法中惦积,在執(zhí)行代碼塊之前接校,會(huì)先判斷當(dāng)前線程、當(dāng)前隊(duì)列是否為nil狮崩。若不為nil蛛勉,則會(huì)在后臺(tái)開啟一個(gè)串行異步線程隊(duì)列。而self.backgroundScheduler通過[RACScheduler scheduler]創(chuàng)建并實(shí)例化的睦柴,最終可以追溯到以下代碼中:
+ (RACScheduler *)schedulerWithPriority:(RACSchedulerPriority)priority name:(NSString *)name {
return [[RACTargetQueueScheduler alloc] initWithName:name targetQueue:dispatch_get_global_queue(priority, 0)];
}
上述代碼意味著是由RACTargetQueueScheduler類初始化诽凌,而RACTargetQueueScheduler是RACQueueScheduler的子類。
而RACTargetQueueScheduler類實(shí)例化方法實(shí)現(xiàn)中坦敌,使用GCD在目標(biāo)線程里創(chuàng)建了一個(gè)串行隊(duì)列侣诵。
那么,此時(shí)來看下RACQueueScheduler類的schedule方法實(shí)現(xiàn):
- (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;
}
此處使用GCD開啟了一個(gè)異步線程狱窘,在后臺(tái)執(zhí)行下一步操作杜顺,作為當(dāng)前的Scheduler去執(zhí)行。所以說蘸炸,RACQueueScheduler類實(shí)現(xiàn)的schedule方法是在后臺(tái)創(chuàng)建一個(gè)串行隊(duì)列異步線程來實(shí)現(xiàn)最終的代碼塊執(zhí)行躬络。
在該方法中,首先找到當(dāng)前的Scheduler隊(duì)列搭儒;然后從當(dāng)前線程字典中找到關(guān)于RACSchedulerCurrentSchedulerKey鍵值并將RACScheduler自己賦值給它穷当。
如果當(dāng)前Scheduler隊(duì)列不為空越锈,則會(huì)把當(dāng)前的Scheduler隊(duì)列存入到當(dāng)前線程字典的RACSchedulerCurrentSchedulerKey鍵值中;若為空膘滨,則把當(dāng)前線程字典的RACSchedulerCurrentSchedulerKey鍵值內(nèi)容全部刪除甘凭。一旦刪除,意味著當(dāng)前線程中的隊(duì)列已不存在火邓。當(dāng)隊(duì)列不存在時(shí)丹弱,會(huì)利用Objective-C的動(dòng)態(tài)機(jī)制,會(huì)自動(dòng)修復(fù)重啟當(dāng)前的隊(duì)列铲咨。
上面有一段代碼:
@autoreleasepool {
block();
}
此段代碼中的block執(zhí)行時(shí)躲胳,也就是創(chuàng)建RACSignal信號(hào)的block中,會(huì)有臨時(shí)變量的產(chǎn)生纤勒,autoreleasepool意味著延遲釋放坯苹。其中涉及到runloop知識(shí)范圍,此處不做深入討論摇天。
以上內(nèi)容主要講解了RACScheduler類以及三種子類的作用與實(shí)現(xiàn)過程原理粹湃,后續(xù)會(huì)繼續(xù)探究RAC內(nèi)部實(shí)現(xiàn)的具體流程。
該文章首次發(fā)表在 簡(jiǎn)書:我只不過是出來寫寫代碼 博客泉坐,并自動(dòng)同步至 騰訊云:我只不過是出來寫寫iOS 博客