日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ReactiveCocoa源码拆分解析(四)

發布時間:2023/11/29 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ReactiveCocoa源码拆分解析(四) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

(整個關于ReactiveCocoa的代碼工程可以在https://github.com/qianhongqiang/QHQReactive下載)

上一章節簡要的說明了如何實現的熱信號。但是像那么寫,貌似不是非常優雅。這一章節我們會把冷熱信號轉換寫的跟ReactiveCocoa一樣優雅。

ReactiveCocoa內部是如何實現冷熱信號轉換的呢?我們來看個例子

? ?RACSignal *replayLazilySignal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

?? ? ? NSLog(@"replaylazily---sendAction");

? ? ? ? [subscriber sendNext:@"replaylazily"];

? ? ? ? return nil;

? ? }] replayLazily];

?? ?

? ? [replayLazilySignal subscribeNext:^(id x) {

? ? ? ? NSLog(@"subscribe1----%@",x);

? ? }];

?? ?

? ? [replayLazilySignal subscribeNext:^(id x) {

? ? ? ? NSLog(@"subscribe2----%@",x);

? ? }];

沒錯,只是在原有信號的基礎上,增加了一個replayLazily方法掉用。我們從輸出上可以看看,是否轉為了熱信號。

2015-12-29 13:28:03.588 xxxxxx[40933:6054173] <xxxxxx:(232)> replaylazily---sendAction

2015-12-29 13:28:03.589 xxxxxx[40933:6054173] <xxxxxx:(238)> subscribe1----replaylazily

2015-12-29 13:28:03.589 xxxxxx[40933:6054173] <xxxxxx:(242)> subscribe2----replaylazily


發送只有1次,被訂閱了兩次。那么我們也朝這個目標出發。

我們這次讓一個熱信號QHQSubject去訂閱最初的冷信號,偷偷的將返回改成這個熱信號,偷梁換柱而神不知鬼不覺。

-(QHQSignal *)replayLazily {

? ? QHQMulticastConnection *conn = [[QHQMulticastConnection alloc] initWithSourceSignal:self outSignalSubject:[[QHQSubject alloc] init]];

? ? [conn connectSignal];

? ? return conn.connSignal;

}

這里用到了一個新類,用于做這層轉化QHQMulticastConnection,它需要一個源,和一個訂閱信號。當執行connectSignal方法后,讓熱信號訂閱最初信號。

-(void)connectSignal {

? ? [_sourceSignal subscribe:_connSignal];

}

讓熱信號稱為接下來流的來源??此埔呀浱煲聼o縫了,執行下,看看結果如何

-(void)demoFourReplayLazily {

? ? QHQSignal *replaySignal = [[QHQSignal createSignal:^(id subscriber) {

? ? ? ? [subscriber sendNext:@"replaySignal---send"];

? ? }] replayLazily];

?? ?

? ? [replaySignal subscribeNext:^(id x) {

? ? ? ? NSLog(@"sub1 ---- %@",x);

? ? }];

?? ?

? ? [replaySignal subscribeNext:^(id x) {

? ? ? ? NSLog(@"sub2 ---- %@",x);

? ? }];

}

2015-12-29 13:39:59.345 PageText[42204:6070078] replaySignal----send


怎么沒有輸出訂閱的結果呢?確實不應該輸出結果,開始分析下原因。當你掉用replayLazily方法時,你已經偷偷摸摸將信號換成了QHQSubject,在這個過程中,你已經訂閱了信號,也就是最終的輸出結果。讓后你再去訂閱這個QHQSubject的時候,它做不了任何事情,因為信號的發送已經過去了,過去了,了。我們可以做個延遲發送事件看看。

? ??QHQSignal *replaySignal = [[QHQSignal createSignal:^(id subscriber) {

? ? ? ? NSLog(@"replaySignal----send");

? ? ? ? [subscriber sendNext:@"replaySignal---send"];

?? ? ? ?

? ? ? ? dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

? ? ? ? ? ? NSLog(@"Delay-----replaySignal----send");

? ? ? ? ? ? [subscriber sendNext:@"Delay-----replaySignal---send"];

? ? ? ? });

?? ? ? ?

? ? }] replayLazily];

?? ?

? ? [replaySignal subscribeNext:^(id x) {

? ? ? ? NSLog(@"sub1 ---- %@",x);

? ? }];

?? ?

? ? [replaySignal subscribeNext:^(id x) {

? ? ? ? NSLog(@"sub2 ---- %@",x);

? ? }];

發送了兩次事件,一次是理解發送,另一次做了延遲??纯唇Y果

2015-12-29 13:45:35.560 PageText[42399:6074028] replaySignal----send

2015-12-29 13:45:37.561 PageText[42399:6074028] Delay-----replaySignal----send

2015-12-29 13:45:37.562 PageText[42399:6074028] sub1 ---- Delay-----replaySignal---send

2015-12-29 13:45:37.562 PageText[42399:6074028] sub2 ---- Delay-----replaySignal---send

延遲發送的事件確實收到了,說明確實轉化成了熱信號。但是我們總不能每次都延遲一下吧,當然我們可以搞定這個問題,我們讓熱信號把事件存起來,訂閱這訂閱后把事件都發送出去。這個時候需要一個可以保存事件的熱信號。

因此,我們創建了一個新類繼承于QHQSubject

@interface QHQReplaySubject ()

@property (nonatomic, assign) NSUInteger capacity;

@property (nonatomic, strong) NSMutableArray *values;

@end

它會將每次發送來的事件保存在values數組中,如果數組容量大于承載capacity,將會移除掉更早的事件

-(void)sendNext:(id)next {

? ? [_values addObject:next];

? ? [super sendNext:next];

?? ?

? ? if (_values.count >_capacity) {

? ? ? ? [_values removeObjectAtIndex:0];

? ? }

}

它每次被訂閱時,都需要首先將已經保存的信號發送給訂閱著

-(void)subscribe:(id<QHQSubscrib>)sub {

? ? for (id value in _values) {

? ? ? ? [sub sendNext:value];

? ? }

? ? [self.subscribers addObject:sub];

}

這樣,第一次的信號就不會丟失。

-(QHQSignal *)replayLazily {

? ? QHQMulticastConnection *conn = [[QHQMulticastConnection alloc] initWithSourceSignal:self outSignalSubject:[QHQReplaySubject replaySubjectWithCapacity:1]];

? ? [conn connectSignal];

? ? return conn.connSignal;

}

簡單的將熱信號替換成能夠保存1個老信號的熱信號,那么問題迎刃而解

2015-12-29 14:02:00.766 PageText[43381:6084580] replaySignal----send

2015-12-29 14:02:00.767 PageText[43381:6084580] sub1 ---- replaySignal---send

2015-12-29 14:02:00.767 PageText[43381:6084580] sub2 ---- replaySignal---send

2015-12-29 14:02:02.768 PageText[43381:6084580] Delay-----replaySignal----send

2015-12-29 14:02:02.769 PageText[43381:6084580] sub1 ---- Delay-----replaySignal---send

2015-12-29 14:02:02.770 PageText[43381:6084580] sub2 ---- Delay-----replaySignal---send

?

輸出符合預期

實際上,RAC也是這么做的,不過它將所有的接口都處理成線程安全的。

轉載于:https://www.cnblogs.com/qianhongqiang/p/5085556.html

總結

以上是生活随笔為你收集整理的ReactiveCocoa源码拆分解析(四)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。