Reactive Cocoa 技術(shù)整理

1.Reactive Cocoa解決了什么問(wèn)題

  1. 傳統(tǒng)iOS開(kāi)發(fā)過(guò)程中豫喧,狀態(tài)以及狀態(tài)之間依賴過(guò)多的問(wèn)題
  2. 傳統(tǒng)MVC架構(gòu)的問(wèn)題:Controller比較復(fù)雜埋涧,可測(cè)試性差
  3. 提供統(tǒng)一的消息傳遞機(jī)制

2.基本概念

一個(gè)很好的比喻

可以把信號(hào)想象成水龍頭当犯,只不過(guò)里面不是水积糯,而是玻璃球(value)烧颖,直徑跟水管的內(nèi)徑一樣近迁,這樣就能保證玻璃球是依次排列明肮,不會(huì)出現(xiàn)并排的情況(數(shù)據(jù)都是線性處理的菱农,不會(huì)出現(xiàn)并發(fā)情況)。水龍頭的開(kāi)關(guān)默認(rèn)是關(guān)的柿估,除非有了接收方(subscriber)循未,才會(huì)打開(kāi)。這樣只要有新的玻璃球進(jìn)來(lái)官份,就會(huì)自動(dòng)傳送給接收方只厘。可以在水龍頭上加一個(gè)過(guò)濾嘴(filter)舅巷,不符合的不讓通過(guò)羔味,也可以加一個(gè)改動(dòng)裝置,把球改變成符合自己的需求(map)钠右。也可以把多個(gè)水龍頭合并成一個(gè)新的水龍頭(combineLatest:reduce:)赋元,這樣只要其中的一個(gè)水龍頭有玻璃球出來(lái),這個(gè)新合并的水龍頭就會(huì)得到這個(gè)球飒房。

信號(hào)(Signal):信號(hào)就是流搁凸,RAC中所有的信號(hào)都是RACStream的子類。信號(hào)有冷熱之分狠毯,信號(hào)也有中繼护糖、改變等操作。信號(hào)是讓訂閱者去訂閱嚼松,然后觸發(fā)對(duì)應(yīng)事件嫡良。

  • 冷信號(hào)(Cold):是被動(dòng)的信號(hào)锰扶,只有當(dāng)你訂閱的時(shí)候,它才會(huì)發(fā)布消息寝受。只能一對(duì)一坷牛,當(dāng)有不同的訂閱者,消息會(huì)從新完整發(fā)送很澄。
  • 熱信號(hào)(Hot):是主動(dòng)的信號(hào)京闰,即使你沒(méi)有訂閱事件,它仍然會(huì)時(shí)刻推送甩苛□彘梗可以有多個(gè)訂閱者,是一對(duì)多浪藻,信號(hào)可以與訂閱者共享信息捐迫。

訂閱者(Subscriber):負(fù)責(zé)接收信號(hào)執(zhí)行操作,都必須實(shí)現(xiàn)RACSubscriber協(xié)議爱葵。訂閱者之間的關(guān)系原則上是平等的施戴,但實(shí)際操作上也是有先后順序,而且還有副作用的情況需要考慮萌丈。

事件類型:信號(hào)(RACSignal)發(fā)送給訂閱者(Subscriber)的事件類型有三種赞哗,分別是next、error辆雾、completed肪笋。一個(gè)signal在因error終止或者完成前,可以發(fā)送任意數(shù)量的next事件度迂。三種事件對(duì)應(yīng)函數(shù)如下:

subscribeNext:^(id x)

subscribeError:^(NSError *error)

subscribeCompleted:^

有些地方需要注意下藤乙,比如把signal作為local變量時(shí),如果沒(méi)有被subscribe惭墓,那么方法執(zhí)行完后坛梁,該變量會(huì)被dealloc。但如果signal有被subscribe腊凶,那么subscriber會(huì)持有該signal划咐,直到signal sendCompleted或sendError時(shí),才會(huì)解除持有關(guān)系钧萍,signal才會(huì)被dealloc褐缠。

副作用(Side Effect):在每一次訂閱的是時(shí)候都會(huì)觸發(fā)對(duì)應(yīng)的操作,導(dǎo)致訂閱者收到信號(hào)的時(shí)候风瘦,結(jié)果會(huì)和其他訂閱者不同队魏。添加附加操作,如doNext:因?yàn)樗歉郊硬僮魍蛏Γ⒉桓淖兪录旧怼?/p>

生命周期:一個(gè)信號(hào)的生命周期是由任意個(gè) next 事件和一個(gè) error 事件或一個(gè) completed事件組成的胡桨。

Reactive結(jié)構(gòu)圖

3. RACStream

RACStream結(jié)構(gòu)圖
RACStream 是一個(gè)抽象類俐载,通常情況下,我們并不會(huì)去實(shí)例化它登失,而是直接使用它的兩個(gè)子類 RACSignal 和 RACSequence 。

RACSignal

RACSignal 并非只有一個(gè)類挖炬,事實(shí)上揽浙,它的一系列功能是通過(guò)類簇來(lái)實(shí)現(xiàn)的。

  • RACEmptySignal :空信號(hào)意敛,用來(lái)實(shí)現(xiàn) RACSignal 的 +empty 方法馅巷;
  • RACReturnSignal :一元信號(hào),用來(lái)實(shí)現(xiàn) RACSignal 的 +return: 方法草姻;
  • RACDynamicSignal :動(dòng)態(tài)信號(hào)钓猬,使用一個(gè) block 來(lái)實(shí)現(xiàn)訂閱行為,我們?cè)谑褂?RACSignal 的 +createSignal: 方法時(shí)創(chuàng)建的就是該類的實(shí)例撩独;
  • RACErrorSignal :錯(cuò)誤信號(hào)敞曹,用來(lái)實(shí)現(xiàn) RACSignal 的 +error: 方法;
  • RACChannelTerminal :通道終端综膀,代表 RACChannel 的一個(gè)終端澳迫,用來(lái)實(shí)現(xiàn)雙向綁定。

對(duì)于 RACSignal 類簇來(lái)說(shuō)剧劝,最核心的方法莫過(guò)于 -subscribe: 了橄登,這個(gè)方法封裝了訂閱者對(duì)信號(hào)源的一次訂閱過(guò)程,它是<font color = red>訂閱者與信號(hào)源產(chǎn)生聯(lián)系的唯一入口</font>讥此。

RACSequence

代表的是一個(gè)不可變的值的序列拢锹,從嚴(yán)格意義上講,RACSequence 并不能算作是信號(hào)源萄喳,因?yàn)樗⒉荒芟?RACSignal 那樣卒稳,可以被訂閱者訂閱,但是它與 RACSignal 之間可以非常方便地進(jìn)行轉(zhuǎn)換取胎。RACSequence 存在的最大意義就是為了簡(jiǎn)化 Objective-C 中的集合操作展哭。

從理論上說(shuō),一個(gè) RACSequence 由兩部分組成:

  • head :指的是序列中的第一個(gè)對(duì)象闻蛀,如果序列為空匪傍,則為 nil ;
  • tail :指的是序列中除第一個(gè)對(duì)象外的其它所有對(duì)象觉痛,同樣的役衡,如果序列為空,則為 nil 薪棒。

RACSequence 的一系列功能也是通過(guò)類簇來(lái)實(shí)現(xiàn)的手蝎,它共有九個(gè)用來(lái)實(shí)現(xiàn)不同功能的私有子類:

  • RACUnarySequence :一元序列榕莺,用來(lái)實(shí)現(xiàn) RACSequence 的 +return: 方法;
  • RACIndexSetSequence :用來(lái)遍歷索引集棵介;
  • RACEmptySequence :空序列钉鸯,用來(lái)實(shí)現(xiàn) RACSequence 的 +empty 方法;
  • RACDynamicSequence :動(dòng)態(tài)序列邮辽,使用 blocks 來(lái)動(dòng)態(tài)地實(shí)現(xiàn)一個(gè)序列唠雕;
  • RACSignalSequence :用來(lái)遍歷信號(hào)中的值;
  • RACArraySequence :用來(lái)遍歷數(shù)組中的元素吨述;
  • RACEagerSequence :非懶計(jì)算的序列岩睁,在初始化時(shí)立即計(jì)算所有的值;
  • RACStringSequence :用來(lái)遍歷字符串中的字符揣云;
  • RACTupleSequence :用來(lái)遍歷元組中的元素捕儒。

4.RACCommand

RACCommand:代表著與交互后即將執(zhí)行的一段流程。通常這個(gè)交互是UI層級(jí)的邓夕,比如你點(diǎn)擊個(gè)Button刘莹。RACCommand可以方便的將Button與enable狀態(tài)進(jìn)行綁定,也就是當(dāng)enable為NO的時(shí)候翎迁,這個(gè)RACCommand將不會(huì)執(zhí)行栋猖。RACCommand還有一個(gè)常見(jiàn)的策略:allowsConcurrentExecution,默認(rèn)為NO汪榔,也就是是當(dāng)你這個(gè)command正在執(zhí)行的話蒲拉,你多次點(diǎn)擊Button是沒(méi)有用的。創(chuàng)建一個(gè)RACCommand的返回值是一個(gè)Signal痴腌,這個(gè)Signal會(huì)返回next或者complete或者error雌团。它有幾個(gè)比較重要的屬性:executionSignals / errors / executing。

  • executionSignals是signal of signals士聪,如果直接subscribe的話會(huì)得到一個(gè)signal锦援,而不是我們想要的value,所以一般會(huì)配合switchToLatest剥悟。
  • errors灵寺。跟正常的signal不一樣,RACCommand的錯(cuò)誤不是通過(guò)sendError來(lái)實(shí)現(xiàn)的区岗,而是通過(guò)errors屬性傳遞出來(lái)的略板。
  • executing表示該command當(dāng)前是否正在執(zhí)行。

5.Reactive Cocoa的使用

combineLatest(聚合信號(hào)):把不同信號(hào)產(chǎn)生的最新的值聚合在一起慈缔,并生成一個(gè)新的信號(hào)叮称。每次這兩個(gè)源信號(hào)的任何一個(gè)產(chǎn)生新值時(shí),reduce block都會(huì)執(zhí)行,block的返回值會(huì)發(fā)給下一個(gè)信號(hào)瓤檐。

Map(轉(zhuǎn)換):Map是接收到信號(hào)后赂韵,對(duì)信號(hào)的返回值處理,然后根據(jù)需要改變信號(hào)的返回值挠蛉,繼續(xù)傳遞該信號(hào)祭示。

Injecting effects(注入效果):對(duì)信號(hào)做一些處理 -doNext: -doError: -doCompleted:。

Filtering(過(guò)濾):過(guò)濾不符合需求的信號(hào)谴古。

FlattenMap(平鋪拓?fù)洌?/strong>:收到信號(hào)后绍移,對(duì)信號(hào)返回值進(jìn)行處理后,返回一個(gè)新的信號(hào)讥电,可以改變信號(hào)的返回值。

Flatten(平鋪):當(dāng)訂閱者的數(shù)量達(dá)到最大當(dāng)前訂閱數(shù)的時(shí)候轧抗,合并接收者發(fā)送的各種信號(hào)到一個(gè)平鋪信號(hào)中恩敌。新的信號(hào)會(huì)像其他信號(hào)一樣被排隊(duì)、訂閱横媚。

Concat(拼接):一個(gè)信號(hào)拼接到另一個(gè)信號(hào)后面

····

6.RACSignal (Debugging)

    /// Logs all events that the receiver sends.
- (RACSignal *)logAll;

/// Logs each `next` that the receiver sends.
- (RACSignal *)logNext;

/// Logs any error that the receiver sends.
- (RACSignal *)logError;

/// Logs any `completed` event that the receiver sends.
- (RACSignal *)logCompleted;

調(diào)試輔助函數(shù)纠炮,可以觀察信號(hào)的關(guān)閉傳遞等。

附:

函數(shù)式編程(Functional Programming):使用高階函數(shù)灯蝴,例如函數(shù)用其他函數(shù)作為參數(shù)恢口。

響應(yīng)式編程(Reactive Programming):關(guān)注于數(shù)據(jù)流和變化傳播。響應(yīng)式編程可以避免使用追蹤瞬時(shí)狀態(tài)的的實(shí)例變量穷躁。

RAC()宏:等價(jià)于產(chǎn)生信號(hào)耕肩、傳遞信號(hào),以及訂閱信號(hào)问潭。針對(duì)某個(gè)對(duì)象的一個(gè)屬性進(jìn)行綁定猿诸,信號(hào)返回值是對(duì)屬性的賦值

取消信號(hào):在一個(gè)completed或者error事件之后狡忙,訂閱會(huì)自動(dòng)移除梳虽;也可以通過(guò)RACDisposable 手動(dòng)移除訂閱。

雙向綁定:兩邊任何一邊變化灾茁,都會(huì)對(duì)另一邊產(chǎn)生影響窜觉。eg. RACChannelTo(self, blockShowText) = RACChannelTo(self.viewModel, blockShowText);

FlattenMap和Map的區(qū)別:Map是通過(guò)FlattenMap來(lái)實(shí)現(xiàn)的,Map只是改變分發(fā)的值北专。而FlattenMap不僅可以獲得上一個(gè)信號(hào)的值禀挫,還能激活下一個(gè)信號(hào),形成這種鏈?zhǔn)椒磻?yīng)逗余。Map是FlattenMap在流中信號(hào)數(shù)量為1特咆,而且信號(hào)值是block的返回值的特殊情況。Map是改變一個(gè)信號(hào)的返回值,F(xiàn)lattenMap是創(chuàng)建一個(gè)新的信號(hào)腻格。

MVVM概述

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末画拾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子菜职,更是在濱河造成了極大的恐慌青抛,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酬核,死亡現(xiàn)場(chǎng)離奇詭異蜜另,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)嫡意,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門举瑰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人蔬螟,你說(shuō)我怎么就攤上這事此迅。” “怎么了旧巾?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵耸序,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我鲁猩,道長(zhǎng)坎怪,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任廓握,我火速辦了婚禮搅窿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘隙券。我一直安慰自己戈钢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布是尔。 她就那樣靜靜地躺著殉了,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拟枚。 梳的紋絲不亂的頭發(fā)上薪铜,一...
    開(kāi)封第一講書(shū)人閱讀 50,050評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音恩溅,去河邊找鬼隔箍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛脚乡,可吹牛的內(nèi)容都是我干的蜒滩。 我是一名探鬼主播滨达,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼俯艰!你這毒婦竟也來(lái)了捡遍?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤竹握,失蹤者是張志新(化名)和其女友劉穎画株,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體啦辐,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谓传,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了芹关。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片续挟。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖侥衬,靈堂內(nèi)的尸體忽然破棺而出庸推,到底是詐尸還是另有隱情,我是刑警寧澤浇冰,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站聋亡,受9級(jí)特大地震影響肘习,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜坡倔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一漂佩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧罪塔,春花似錦投蝉、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至佃蚜,卻和暖如春庸娱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谐算。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工熟尉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人洲脂。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓斤儿,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子往果,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • RAC使用測(cè)試Demo下載:github.com/FuWees/WPRACTestDemo 1.ReactiveC...
    FuWees閱讀 6,362評(píng)論 3 10
  • 前言由于時(shí)間的問(wèn)題疆液,暫且只更新這么多了,后續(xù)還會(huì)持續(xù)更新本文《最快讓你上手ReactiveCocoa之進(jìn)階篇》棚放,目...
    Karos_凱閱讀 1,733評(píng)論 0 6
  • 標(biāo)簽: iOS RAC 概述 ReactiveCocoa是一個(gè)函數(shù)響應(yīng)式編程框架枚粘,它能讓我們脫離Cocoa AP...
    GodyZ閱讀 7,516評(píng)論 16 97
  • 1.ReactiveCocoa簡(jiǎn)介 ReactiveCocoa(簡(jiǎn)稱為RAC),是由Github開(kāi)源的一個(gè)應(yīng)用于i...
    亂了夏末丶藍(lán)了海閱讀 768評(píng)論 0 0
  • 前言 很多blog都說(shuō)ReactiveCocoa好用,然后各種秀自己如何靈活運(yùn)用ReactiveCocoa飘蚯,但是感...
    RainyGY閱讀 1,328評(píng)論 0 1