ReactiveCocoa 入門教程(一)

1.ReactiveCocoa簡介


RAC 是一個 iOS 中的函數(shù)式響應式編程框架硕盹,是Github 在開發(fā) GitHub for Mac 過程中的一個副產(chǎn)品,他提供了一系列用來組合和轉(zhuǎn)換值流的 API吝岭,為事件的處理定義了一個標準接口,大大方便了開發(fā)者去管理各種事件的處理陪腌,結(jié)果就是開發(fā)者能從關(guān)注業(yè)務實現(xiàn)的細節(jié)上脫身烹骨,轉(zhuǎn)變?yōu)殚_發(fā)者只需要關(guān)心業(yè)務本身就好了,是不是聽起來很神奇的樣子喧枷,接下來就讓我們進入開發(fā)的另一片天空吧虹统!

2.ReactiveCocoa作用


RAC關(guān)鍵解決的問題是開發(fā)中經(jīng)彻耄回見的“低聚合,高耦合”問題车荔。

在RAC出現(xiàn)之前渡冻,我們編寫iOS代碼,大部分都是在響應一些事件:按鈕點擊忧便、接收網(wǎng)絡消息族吻、屬性變化等等。但處理事件的形式在蘋果官方API中卻有好幾種:如target-action茬腿、代理方法呼奢、KVO、回調(diào)或其它切平。以上這幾種握础,往往在一個項目中基本都會使用到,在不同的地方會出現(xiàn)很多處理事件的形式悴品,這就帶來了不能很好統(tǒng)一管理問題禀综。因此,我們想苔严,有沒有一個統(tǒng)一管理的解決方案呢定枷?這個方案又是怎樣的呢?到這里ReactiveCocoa就該粉墨登場了届氢,它出現(xiàn)的目的就是為了解決統(tǒng)一標準去管理代碼中的事件欠窒。

3.編程思想


ReactiveCocoa結(jié)合了幾種編程風格:

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

響應式編程(Reactive Programming):關(guān)注于數(shù)據(jù)流和變化傳播岖妄。

所以,你可能聽說過ReactiveCocoa被描述為函數(shù)響應式編程(FRP)框架寂祥。

以后使用RAC解決問題荐虐,就不需要考慮調(diào)用順序,直接考慮結(jié)果丸凭,把每一次操作都寫成一系列嵌套的方法中福扬,使代碼高聚合,方便管理惜犀。

4.底層原理


? ? ? 1铛碑、運用的是Hook(鉤子)思想,Hook是一種用于改變API(應用程序編程接口:方法)執(zhí)行結(jié)果的技術(shù).

? ? ? 2虽界、Hook用處:截獲API調(diào)用的技術(shù)亚茬。

? ? ? 3、Hook原理:在每次調(diào)用一個API返回結(jié)果之前浓恳,先執(zhí)行你自己的方法刹缝,改變結(jié)果的輸出。

5.常見類和常見功能


信號(signal)— RACSignal類

本質(zhì):是一種流(流是值的序列化的抽象)

說明:一般表示將來有數(shù)據(jù)傳遞颈将,只要有數(shù)據(jù)改變梢夯,信號內(nèi)部接收到數(shù)據(jù),就會馬上發(fā)出數(shù)據(jù)晴圾。

事件類型:

? ? ? ? next:發(fā)送數(shù)據(jù)到下一個管道

? ? ? ? error:發(fā)送數(shù)據(jù)失敗

? ? ? ? completed:發(fā)送數(shù)據(jù)完成

用法:需要訂閱不同的事件類型才能發(fā)揮作用颂砸,即調(diào)用下面這些實例方法

- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock;

- (RACDisposable *)subscribeError:(void (^)(NSError *error))errorBlock;

- (RACDisposable *)subscribeCompleted:(void (^)(void))completedBlock;

......

例子:ReactiveCocoa框架使用category來為很多基本UIKit控件添加signal。這樣你就能給控件添加訂閱了死姚,text field的rac_textSignal就是這么來的人乓。

[self.usernameTextField.rac_textSignal subscribeNext:^(id x) {

NSLog(@"x:%@",x);

}];

過濾 — Filter

說明:過濾信號,使用它可以獲取滿足條件的信號都毒,舉個形象的比喻就是一張可以自由設置網(wǎng)口大小的漁網(wǎng)色罚,根據(jù)自己需要,對網(wǎng)口進行設置就可以捕到特定規(guī)格的魚账劲。

用法:在用戶登錄時戳护,我們需要關(guān)心用戶名長度是否符合要求,比如要求字符長度超過3瀑焦,那么就可以使用Filter來達到這個目的腌且,如下:

RACSignal *validUsernameSignal =

[self.usernameTextField.rac_textSignal filter:^BOOL(NSString *value) {

return value.length > 3;

}];

映射 — Map

說明:把源信號內(nèi)容映射成新的內(nèi)容净神,簡單點說就是將數(shù)據(jù)改成自己想要的數(shù)據(jù)冗锁。

用法:還是用登錄這個場景,我們需要關(guān)心用戶名長度是否符合要求棱貌,比如字符長度超過3才進行下一步處理禀晓,如下:

RACSignal *usernameLengthSignal =

[[self.usernameTextField.rac_textSignal map:^id(NSString *value) {

return @(value.length);

}];

狀態(tài)推導 — RAC()

說明:用于給某個對象的某個屬性綁定精续。

用法:比如只要文本框文字改變,就會修改label的文字

RAC(self.labelView,text) = _textField.rac_textSignal;

聚合信號

說明:聚合任意數(shù)量的信號匆绣,然后生成一個新的信號

用法:比如登錄按鈕只有當用戶名和密碼輸入框的輸入都有效時才能進行點擊

// 創(chuàng)建聚合信號

RACSignal *signUpActiveSignal =

[RACSignal combineLatest:@[validUsernameSignal, validPasswordSinal]

reduce:^id(NSNumber *usernameValid, NSNumber *passwordValid){

return @([usernameValid boolValue] && [passwordValid boolValue]);

}];

// 綁定按鈕

[signUpActiveSignal subscribeNext:^(NSNumber *signupActive) {

@strongify(self)

self.signInButton.enabled = [signupActive boolValue];

}];

創(chuàng)建信號

說明:創(chuàng)建一個信號驻右,用于執(zhí)行信號中的Block,只要有訂閱者崎淳,Block中的內(nèi)容就會被執(zhí)行堪夭。

用法:比如點擊按鈕進行登錄時,就可以創(chuàng)建一個信號拣凹,然后進行訂閱森爽,然后執(zhí)行登錄的業(yè)務邏輯處理

// 創(chuàng)建信號

- (RACSignal *)signInSignal {

@weakify(self)

return [RACSignal createSignal:^RACDisposable *(id subscriber) {

@strongify(self)

[self.signInService signInWithUsername:self.usernameTextField.text

password:self.passwordTextField.text

complete:^(BOOL success) {

[subscriber sendNext:@(success)];

// 必須創(chuàng)建完成時間

[subscriber sendCompleted];

}];

return nil;

}];

}

// 點擊登錄按鈕

[[[self.signInButton rac_signalForControlEvents:UIControlEventTouchUpInside]

map:^id(id value) {

@strongify(self)

return [self signInSignal];

}] subscribeNext:^(id x) {

NSLog(@"Sign in result: %@", x);

}];

信號中的信號 — map —> flattenMap

說明:換句話說就是一個外部信號里面還有一個內(nèi)部信號。

用法:比如上面這個栗子嚣镜,訂閱后發(fā)送的數(shù)據(jù) x 類型最終還是信號爬迟,而不是創(chuàng)建信號時發(fā)送的NSNumber類型:

// 點擊登錄按鈕(Map)

[[[self.signInButton rac_signalForControlEvents:UIControlEventTouchUpInside]

map:^id(id value) {

@strongify(self)

return [self signInSignal];

}] subscribeNext:^(id x) {

NSLog(@"Sign in result: %@", x);// X類型還是RACSignal

}];

?

// 點擊登錄按鈕(FlattenMap)

[[[self.signInButton rac_signalForControlEvents:UIControlEventTouchUpInside]

flattenMap:^id(id value) {

@strongify(self)

return [self signInSignal];

}] subscribeNext:^(id x) {

NSLog(@"Sign in result: %@", x);// X類型是NSNumber

}];

FlatternMap和Map的區(qū)別:

FlatternMap中的Block返回信號。

Map中的Block返回對象菊匿。

開發(fā)中付呕,如果信號發(fā)出的值不是信號计福,映射一般使用Map

開發(fā)中,如果信號發(fā)出的值是信號徽职,映射一般使用FlatternMap

總結(jié):signalOfsignals用FlatternMap象颖。

添加附加操作(doNext:)

說明:執(zhí)行Next之前,會先執(zhí)行這個Block姆钉,簡單說就是在一段邏輯執(zhí)行前進行攔截说订,然后先執(zhí)行一段特別操作,再操作接下來的邏輯

- (RACSignal *)doNext:(void (^)(id x))block

用法:還是拿登錄的場景來說潮瓶,當?shù)卿泂ervice正在校驗用戶名和密碼時陶冷,登錄按鈕應該是不可點擊的。這會防止用戶多次執(zhí)行登錄操作毯辅。還有埂伦,如果登錄失敗了,用戶再次嘗試登錄時悉罕,應該隱藏錯誤信息赤屋。

6.總結(jié)


ReactiveCocoa的核心就是信號,而它不過就是事件流壁袄,通過訂閱將數(shù)據(jù)發(fā)送出去类早。以上就是本篇筆記的核心概念,哈哈嗜逻,是不是很簡單呢涩僻?

通過以上一些概念和使用場景,我們大概對RAC有了初步的認識栈顷∧嫒眨基礎(chǔ)有了,接下來學習深入的知識點就容易多了萄凤。

參考

1室抽、RayWenderlich ReactiveCocoa Tutorial – The Definitive Introduction: Part 1/2

2、iOS的函數(shù)響應型編程

3靡努、MISSAJJ琴瑟靜聽( Swift 和 Objective-C )iOS 開發(fā)項目電子書

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坪圾,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子惑朦,更是在濱河造成了極大的恐慌兽泄,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件漾月,死亡現(xiàn)場離奇詭異病梢,居然都是意外死亡,警方通過查閱死者的電腦和手機梁肿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門蜓陌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來觅彰,“玉大人,你說我怎么就攤上這事护奈〉蘖” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蛀骇。 經(jīng)常有香客問我厌秒,道長,這世上最難降的妖魔是什么擅憔? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任鸵闪,我火速辦了婚禮,結(jié)果婚禮上暑诸,老公的妹妹穿的比我還像新娘蚌讼。我一直安慰自己,他們只是感情好个榕,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布篡石。 她就那樣靜靜地躺著,像睡著了一般西采。 火紅的嫁衣襯著肌膚如雪凰萨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天械馆,我揣著相機與錄音胖眷,去河邊找鬼。 笑死霹崎,一個胖子當著我的面吹牛珊搀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播尾菇,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼境析,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了错沽?” 一聲冷哼從身側(cè)響起簿晓,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎千埃,沒想到半個月后憔儿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡放可,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年谒臼,在試婚紗的時候發(fā)現(xiàn)自己被綠了朝刊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蜈缤,死狀恐怖拾氓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情底哥,我是刑警寧澤咙鞍,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站趾徽,受9級特大地震影響续滋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜孵奶,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一疲酌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧了袁,春花似錦朗恳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至卢鹦,卻和暖如春臀脏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背冀自。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工揉稚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人熬粗。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓搀玖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親驻呐。 傳聞我的和親對象是個殘疾皇子灌诅,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

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

  • 本文翻譯自ReactiveCocoa Tutorial – The Definitive Introduction...
    張果果灬閱讀 1,277評論 1 29
  • 作為一個iOS開發(fā)者,你寫的每一行代碼幾乎都是在相應某個事件含末,例如按鈕的點擊猜拾,收到網(wǎng)絡消息,屬性的變化(通過KVO...
    jiajia1118閱讀 802評論 0 2
  • 1.ReactiveCocoa常見操作方法介紹佣盒。 1.1 ReactiveCocoa操作須知 所有的信號(RACS...
    萌芽的冬天閱讀 1,021評論 0 5
  • 作為一個iOS開發(fā)者挎袜,你寫的每一行代碼幾乎都是在相應某個事件,例如按鈕的點擊,收到網(wǎng)絡消息盯仪,屬性的變化(通過KVO...
    不作不會死閱讀 448評論 0 1
  • 前言由于時間的問題紊搪,暫且只更新這么多了,后續(xù)還會持續(xù)更新本文《最快讓你上手ReactiveCocoa之進階篇》全景,目...
    Karos_凱閱讀 1,738評論 0 6