iOS之ReactiveCocoa源碼及痛點分析

來源:互聯網
上載者:User

ReactiveCocoa是一個非常複雜的架構,在正式開始介紹它的核心組件前,我們先來看看它的類圖,以便從宏觀上瞭解它的階層:




從上面的類圖中,我們可以看出,ReactiveCocoa 主要由以下四大核心組件構成: 訊號源:RACStream 及其子類; 訂閱者:RACSubscriber 的實作類別及其子類; 調度器:RACScheduler 及其子類; 清潔工:RACDisposable 及其子類。

其中,訊號源又是最核心的部分,其他組件都是圍繞它運作的。






RACSignal和RACSubject的區別 RACSubject:訊號提供者,自己可以充當訊號,又能發送訊號  使用情境: 通常用來代替代理,有了它,就不必要定義代理了

RACSubject使用步驟
1.建立訊號 [RACSubject subject],跟RACSiganl不一樣,建立訊號時沒有block。
2.訂閱訊號 - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
3.發送訊號 sendNext:(id)value


RACSubject:底層實現和RACSignal不一樣。
1.調用subscribeNext訂閱訊號,只是把訂閱者儲存起來,並且訂閱者的nextBlock已經賦值了。
2.調用sendNext發送訊號,遍曆剛剛儲存的所有訂閱者,一個一個調用訂閱者的nextBlock。


RACSubject執行個體 進行map操作之後 , 發送完畢一定要調用-sendCompleted, 否則會出現記憶體流失;  RACSignal執行個體不管是否進行map操作, 不管是否調用-sendCompleted, 都不會出現記憶體流失.
原因 : 因為RACSubject是熱訊號, 為了保證未來有事件發生的時候, 訂閱者可以收到資訊, 所以需要對持有訂閱者!




map 和 flattenMap 的區別 Map適用於:訊號發出的是值
FlatternMap適用於:訊號發出的是訊號 

先來看看RACStream.h文檔說明:


/// Maps `block` across the values in the receiver.

///

/// This corresponds to the `Select` method inRx.(Rx見下面備忘)

///

/// Returns a new stream with the mapped values.

- (instancetype)map:(id (^)(id value))block;

/// Maps `block` across the values in the receiver and flattens the result.

///

/// Note that operators applied _after_ -flattenMap: behave differently from

/// operators _within_ -flattenMap:. See the Examples section below.

///

/// This corresponds to the `SelectMany` method in Rx.

///

/// block - A block which accepts the values in the receiver and returns a new

///         instance of the receiver's class. Returning `nil` from this block is

///         equivalent to returning an empty signal.

///

/// Examples

///

///   [signal flattenMap:^(id x) {

///       // Logs each time a returned signal completes.

///       return [[RACSignal return:x] logCompleted];

///   }];

///

///   [[signal

///       flattenMap:^(id x) {

///           return [RACSignal return:x];

///       }]

///       // Logs only once, when all of the signals complete.

///       logCompleted];

///

/// Returns a new stream which represents the combined streams resulting from

/// mapping `block`.

- (instancetype)flattenMap:(RACStream * (^)(id value))block;
什麼是Rx: “Reactive Extensions(Rx)是 微軟公司的一個類庫,它整合了非同步、基於可觀察(observable)序列的事件驅動編程和LINQ-style的查詢操作。使用Rx,開發人員可以用observable對象描述非同步資料流,使用LINQ操作符非同步查詢資料和使用Schedulers控制非同步過程中的並發。簡而言之,Rx = Observables + LINQ + Schedulers。”

- (void)map {              // Map使用步驟:       // 1.傳入一個block,類型是返回對象,參數是value       // 2.value就是源訊號的內容,直接拿到源訊號的內容做處理       // 3.把處理好的內容,直接返回就好了,不用封裝成訊號,返回的值,就是映射的值。              // Map底層實現:       // 0.Map底層其實是調用flatternMap,Map中block中的返回的值會作為flatternMap中block中的值。       // 1.當訂閱綁定訊號,就會產生bindBlock。       // 3.當源訊號發送內容,就會調用bindBlock(value, *stop)       // 4.調用bindBlock,內部就會調用flattenMap的block       // 5.flattenMap的block內部會調用Map中的block,把Map中的block返回的內容封裝成返回的訊號。       // 5.返回的訊號最終會作為bindBlock中的返回訊號,當做bindBlock的返回訊號。       // 6.訂閱bindBlock的返回訊號,就會拿到綁定訊號的訂閱者,把處理完成的訊號內容發送出來。                            // Map作用:把源訊號的值對應成一個新的值       // 建立訊號       RACSubject *subject = [RACSubject subject];       // 綁定訊號       RACSignal *bindSignal = [subject map:^id(id value) {                      // 返回的類型就是你需要映射的值           return [NSString stringWithFormat:@"ws:%@", value]; //這裡將源訊號發送的“123” 前面拼接了ws:       }];       // 訂閱綁定訊號       [bindSignal subscribeNext:^(id x) {           NSLog(@"%@", x);       }];       // 發送訊號  

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.