ReactiveCocoa學習

版本

到我寫這篇文章為止,ReactiveCocoa版本為5.0.1,搜了很多博客來了解ReactiveCocoa的基礎用法,并不是很多,所以這篇文章算是自己對搜索資源的一個匯總,并加入一些自己在學習中遇到的問題和解決.

RAC 5.0 相比于 4.0 有了巨大的變化,不僅是受 swift 3.0 大升級的影響,RAC 對自身項目結構的也進行了大幅度的調整。這個調整就是將 RAC 拆分為四個庫:ReactiveCocoa, ReactiveSwift, ReactiveObjC, ReactiveObjCBridge.

在項目里現在到底要引入哪些

如果你的項目是純 OC 項目,你需要使用的是 ReactiveObjC 。這個庫里面包含原來 RAC 2 的全部代碼。
如果你只是純 swift 項目,你繼續使用ReactiveCocoa 。但是 RAC 依賴于 ReactiveSwift ,等于你引入了兩個庫。
如果你的項目是 swift 和 OC 混編,你需要同時引用 ReactiveCocoa 和 ReactiveObjCBridge 。但是 ReactiveObjCBridge 依賴于 ReactiveObjC ,所以你就等于引入了 4 個庫。


ReactiveCocoa 試圖解決什么問題

  1. 傳統 iOS 開發過程中,狀態以及狀態之間依賴過多的問題
  2. 傳統 MVC 架構的問題:Controller 比較復雜,可測試性差
  3. 提供統一的消息傳遞機制

傳統 iOS 開發過程中,狀態以及狀態之間依賴過多的問題

我們在開發 iOS 應用時,一個界面元素的狀態很可能受多個其它界面元素或后臺狀態的影響。
例如,在用戶帳戶的登錄界面,通常會有 2 個輸入框(分別輸入帳號和密碼)和一個登錄按鈕。如果我們要加入一個限制條件:當用戶輸入完帳號和密碼,并且登錄的網絡請求還未發出時,確定按鈕才可以點擊。通常情況下,我們需要監聽這兩個輸入框的狀態變化以及登錄的網絡請求狀態,然后修改另一個控件的enabled狀態。
RAC 通過引入信號(Signal)的概念,來代替傳統 iOS 開發中對于控件狀態變化檢查的代理(delegate)模式或 target-action 模式。因為 RAC 的信號是可以組合(combine)的,所以可以輕松地構造出另一個新的信號出來,然后將按鈕的enabled狀態與新的信號綁定。

RAC(self.loginBtn,enabled) = [RACSignal combineLatest:@[self.nameTF.rac_textSignal,
                                                        self.passwordTF.rac_textSignal
                                                        ]
                                                reduce:^(NSString *nameSignal,NSString *pwdSignal){
                                                            return @(nameSignal.length>=0 && pwdSignal.length>=0);
                                                        }];

簡單的解釋一下代碼:
這是將loginBtn的enable屬性和帳號和密碼兩個輸入框綁定,當兩個輸入框的文本都不為空的時候,loginBtn才可以點擊. 注意一點,reduce后面的block并不會自動生成所有的返回值,需要根據自己在前面綁定的幾個信號自己補全,然后直到這部分代碼完全寫完中間可能一直在報錯,不要理他.從RAC的源碼中可以看出來,前面綁定的信號不同后面的block返回值類型也是不同的.

統一消息傳遞機制

iOS 開發中有著各種消息傳遞機制,包括 KVO、Notification、delegation、block 以及 target-action 方式。各種消息傳遞機制使得開發者在做具體選擇時感到困惑. 在引入 RAC 之后,以前散落在action-target或 KVO 的回調函數中的判斷邏輯被統一到了一起.

// KVO
[RACObserve(self, username) subscribeNext:^(id x) {
    NSLog(@" 成員變量 username 被修改成了:%@", x);
}];
// target-action
self.button.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
    NSLog(@" 按鈕被點擊 ");
    return [RACSignal empty];
}];
// Notification
[[[NSNotificationCenter defaultCenter] 
    rac_addObserverForName:UIKeyboardDidChangeFrameNotification         
                    object:nil] 
    subscribeNext:^(id x) {
        NSLog(@" 鍵盤 Frame 改變 ");
    }
];
// Delegate
[[self rac_signalForSelector:@selector(viewWillAppear:)] subscribeNext:^(id x) {
    debugLog(@"viewWillAppear 方法被調用 %@", x);
}];

基礎用法理解參考下面這篇文章吧,是翻譯過來的,寫得很棒,例子層層深入,慢慢讀,就理解RAC的signal了.不過個人感覺想要深入了解,還是得自己多用.
ReactiveCocoa入門教程——第一部

試圖解決 MVC 框架的問題

對于傳統的 Model-View-Controller 的框架,Controller 很容易變得比較龐大和復雜。由于 Controller 承擔了 Model 和 View 之間的橋梁作用,所以 Controller 常常與對應的 View 和 Model 的耦合度非常高,這同時也造成對其做單元測試非常不容易,對 iOS 工程的單元測試大多都只在一些工具類或與界面無關的邏輯類中進行。
RAC 的信號機制很容易將某一個 Model 變量的變化與界面關聯,所以非常容易應用 Model-View-ViewModel 框架。通過引入 ViewModel 層,然后用 RAC 將 ViewModel 與 View 關聯,View 層的變化可以直接響應 ViewModel 層的變化,這使得 Controller 變得更加簡單,由于 View 不再與 Model 綁定,也增加了 View 的可重用性。

MVVM 的作用和問題
MVVM 在實際使用中,確實能夠使得 Model 層和 View 層解耦,但是如果你需要實現 MVVM 中的雙向綁定的話,那么通常就需要引入更多復雜的框架來實現了。
對此,MVVM 的作者 John Gossman 的 批評 應該是最為中肯的。John Gossman 對 MVVM 的批評主要有兩點:

第一點:數據綁定使得 Bug 很難被調試。你看到界面異常了,有可能是你 View 的代碼有 Bug,也可能是 Model 的代碼有問題。數據綁定使得一個位置的 Bug 被快速傳遞到別的位置,要定位原始出問題的地方就變得不那么容易了。
第二點:對于過大的項目,數據綁定需要花費更多的內存。

附:
之前在上家公司用過一個MBMvc的框架來幫助分層,很好用,不過我看了一下github上已經很久沒有更新了,懷疑是不是有什么問題停更了呢, 大家有興趣的可以了解一下這個框架.


摘自:
唐巧 : ReactiveCocoa - iOS開發的新框架

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容