ReactiveCocoa

ReactiveCocoa簡(jiǎn)介

ReactiveCocoa(簡(jiǎn)稱為RAC),是由Github開(kāi)源的一個(gè)應(yīng)用于iOS和OS開(kāi)發(fā)的新框架,Cocoa是蘋(píng)果整套框架的簡(jiǎn)稱,因此很多蘋(píng)果框架喜歡以Cocoa結(jié)尾。

ReactiveCocoa作用

在我們iOS開(kāi)發(fā)過(guò)程中,當(dāng)某些事件響應(yīng)的時(shí)候,需要處理某些業(yè)務(wù)邏輯,這些事件都用不同的方式來(lái)處理。

比如按鈕的點(diǎn)擊使用action,ScrollView滾動(dòng)使用delegate,屬性值改變使用KVO等系統(tǒng)提供的方式。

其實(shí)這些事件,都可以通過(guò)RAC處理

ReactiveCocoa為事件提供了很多處理方法,而且利用RAC處理事件很方便,可以把要處理的事情,和監(jiān)聽(tīng)的事情的代碼放在一起,這樣非常方便我們管理,就不需要跳到對(duì)應(yīng)的方法里。非常符合我們開(kāi)發(fā)中高聚合,低耦合的思想。

編程思想

在開(kāi)發(fā)中我們也不能太依賴于某個(gè)框架,否則這個(gè)框架不更新了,導(dǎo)致項(xiàng)目后期沒(méi)辦法維護(hù),比如之前Facebook提供的Three20框架,在當(dāng)時(shí)也是神器,但是后來(lái)不更新了,也就沒(méi)什么人用了。因此我感覺(jué)學(xué)習(xí)一個(gè)框架,還是有必要了解它的編程思想。

先簡(jiǎn)單介紹下目前咱們已知的編程思想。

3.1 面向過(guò)程:處理事情以過(guò)程為核心,一步一步的實(shí)現(xiàn)。

3.2 面向?qū)ο螅喝f(wàn)物皆對(duì)象

3.3 鏈?zhǔn)骄幊趟枷耄菏菍⒍鄠€(gè)操作(多行代碼)通過(guò)點(diǎn)號(hào)(.)鏈接在一起成為一句代碼,使代碼可讀性好。a(1).b(2).c(3)

? ? ? ?鏈?zhǔn)骄幊烫攸c(diǎn):方法的返回值是block,block必須有返回值(本身對(duì)象),block參數(shù)(需要操作的值)

? ? ? ?代表:masonry框架。

3.4 響應(yīng)式編程思想:不需要考慮調(diào)用順序,只需要知道考慮結(jié)果,類似于蝴蝶效應(yīng),產(chǎn)生一個(gè)事件,會(huì)影響很多東西,這些事件像流一樣的傳播出去,然后影響結(jié)果,借用面向?qū)ο蟮囊痪湓?,萬(wàn)物皆是流。

? ? ? ?代表:KVO運(yùn)用。

3.5 函數(shù)式編程思想:是把操作盡量寫(xiě)成一系列嵌套的函數(shù)或者方法調(diào)用。

? ? ? ?函數(shù)式編程特點(diǎn):每個(gè)方法必須有返回值(本身對(duì)象),把函數(shù)或者Block當(dāng)做參數(shù),block參數(shù)(需要操作的值)block返回值(操作結(jié)果)

? ? ? ?代表:ReactiveCocoa。

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

函數(shù)式編程(Functional Programming)

響應(yīng)式編程(Reactive Programming)

所以,你可能聽(tīng)說(shuō)過(guò)ReactiveCocoa被描述為函數(shù)響應(yīng)式編程(FRP)框架。

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

ReactiveCocoa的簡(jiǎn)單使用

???假設(shè)我們現(xiàn)在有個(gè)登錄界面,需要輸入username和password,然后點(diǎn)擊signinButton,就能發(fā)起登錄請(qǐng)求

[[[self.usernameTextField.rac_textSignal

??map:^id(NSString*text){

? ? return @(text.length);

??filter:^BOOL(NSNumber*length){

? ? return [length integerValue] > 3;

??subscribeNext:^(id x){

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

??}];

代碼解析:這里給username編輯框的事件添加信號(hào)跟蹤,將其映射為文本長(zhǎng)度,超出長(zhǎng)度3的輸出日志。而且ReactiveCocoa的方法特性是都會(huì)返回類對(duì)象自身,方便鏈?zhǔn)秸{(diào)用。

插入介紹一下名詞解釋

信號(hào)(signal)— RACSignal類

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

說(shuō)明:一般表示將來(lái)有數(shù)據(jù)傳遞,只要有數(shù)據(jù)改變,信號(hào)內(nèi)部接收到數(shù)據(jù),就會(huì)馬上發(fā)出數(shù)據(jù)。

事件類型:

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

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

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

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

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

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

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

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

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

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

}];

過(guò)濾?— Filter

說(shuō)明:過(guò)濾信號(hào),使用它可以獲取滿足條件的信號(hào),舉個(gè)形象的比喻就是一張可以自由設(shè)置網(wǎng)口大小的漁網(wǎng),根據(jù)自己需要,對(duì)網(wǎng)口進(jìn)行設(shè)置就可以捕到特定規(guī)格的魚(yú)。

用法:在用戶登錄時(shí),我們需要關(guān)心用戶名長(zhǎng)度是否符合要求,比如要求字符長(zhǎng)度超過(guò)3,那么就可以使用Filter來(lái)達(dá)到這個(gè)目的,如下:

RACSignal *validUsernameSignal =

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

return value.length > 3;

}];

映射?— Map

說(shuō)明:把源信號(hào)內(nèi)容映射成新的內(nèi)容,簡(jiǎn)單點(diǎn)說(shuō)就是將數(shù)據(jù)改成自己想要的數(shù)據(jù)。

用法:還是用登錄這個(gè)場(chǎng)景,我們需要關(guān)心用戶名長(zhǎng)度是否符合要求,比如字符長(zhǎng)度超過(guò)3才進(jìn)行下一步處理,如下:

RACSignal *usernameLengthSignal =

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

return @(value.length);

}];

狀態(tài)推導(dǎo)?— RAC()

說(shuō)明:用于給某個(gè)對(duì)象的某個(gè)屬性綁定。

用法:比如只要編輯框文字改變,就會(huì)修改label的文字

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

聚合信號(hào)

說(shuō)明:聚合任意數(shù)量的信號(hào),然后生成一個(gè)新的信號(hào)

用法:比如登錄按鈕只有當(dāng)用戶名和密碼輸入框的輸入都有效時(shí)才能進(jìn)行點(diǎn)擊

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

RACSignal *signUpActiveSignal =

[RACSignal combineLatest: @[validUsernameSignal, validPasswordSinal]

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

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

}];

參照下圖,來(lái)控制界面對(duì)于用戶操作的響應(yīng)。

- (RACSignal *)signInSignal {

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

? ?[self.signInService?

? ???signInWithUsername:self.usernameTextField.text

? ?? ?? ?? ?? ?password:self.passwordTextField.text

? ?? ?? ?? ?? ?complete:^(BOOL success){

? ?? ?? ?? ?? ?? ???[subscriber sendNext: @(success)];

? ?? ?? ?? ?? ?? ???[subscriber sendCompleted];

? ???}];

returnnil;

}];

}

上面的方法創(chuàng)建了一個(gè)信號(hào),使用用戶名和密碼登錄并調(diào)用接口驗(yàn)證用戶?,F(xiàn)在分解來(lái)看一下。

上面的代碼使用RACSignal的createSignal:方法來(lái)創(chuàng)建信號(hào)。方法的入?yún)⑹且粋€(gè)block,這個(gè)block描述了這個(gè)信號(hào)。當(dāng)這個(gè)信號(hào)有subscriber時(shí),block里的代碼就會(huì)執(zhí)行。

block的入?yún)⑹且粋€(gè)subscriber實(shí)例,它遵循RACSubscriber協(xié)議,協(xié)議里有一些方法來(lái)產(chǎn)生事件,你可以發(fā)送任意數(shù)量的next事件,或者用error\complete事件來(lái)終止。本例中,信號(hào)發(fā)送了一個(gè)next事件來(lái)表示登錄是否成功,隨后是一個(gè)complete事件。

這個(gè)block的返回值是一個(gè)RACDisposable對(duì)象,它允許你在一個(gè)訂閱被取消時(shí)執(zhí)行一些清理工作。當(dāng)前的信號(hào)不需要執(zhí)行清理操作,所以返回nil就可以了。

可以看到,把一個(gè)異步API用信號(hào)封裝是多簡(jiǎn)單!? ?? ?

外部訂閱信號(hào)時(shí),代碼可以這樣寫(xiě):

[[[[self.signInButton

? ?doNext:^(id x){

? ???self.signInButton.enabled =NO;

? ???self.signInFailureText.hidden =YES;

? ?flattenMap:^id(id x){

? ???return[self signInSignal];

? ?subscribeNext:^(NSNumber*signedIn){

? ???self.signInButton.enabled =YES;

? ???BOOL success =[signedIn boolValue];

? ???self.signInFailureText.hidden = success;

? ???if(success){

? ?? ? [self performSegueWithIdentifier: @"signInSuccess" sender:self];

? ???}

? ?}];

因?yàn)樯厦娣椒▌?chuàng)建的是內(nèi)部信號(hào),需要使用flattenMap轉(zhuǎn)換一下??梢钥吹絛oNext:是直接跟在按鈕點(diǎn)擊事件的后面。而且doNext: block并沒(méi)有返回值。因?yàn)樗歉郊硬僮鳎⒉桓淖兪录旧?。整個(gè)流程圖如下:?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容