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); }]; // 發送訊號