到我寫這篇文章為止,ReactiveCocoa版本為5.0.1,搜了很多博客來了解ReactiveCocoa的基礎用法,并不是很多,所以這篇文章算是自己對搜索資源的一個匯總,并加入一些自己在學習中遇到的問題和解決.
RAC 5.0 相比于 4.0 有了巨大的變化殊校,不僅是受 swift 3.0 大升級的影響,RAC 對自身項目結構的也進行了大幅度的調整炬守。這個調整就是將 RAC 拆分為四個庫:ReactiveCocoa, ReactiveSwift, ReactiveObjC, ReactiveObjCBridge.
在項目里現(xiàn)在到底要引入哪些
如果你的項目是純 OC 項目涛救,你需要使用的是 ReactiveObjC 畏邢。這個庫里面包含原來 RAC 2 的全部代碼。
如果你只是純 swift 項目州叠,你繼續(xù)使用ReactiveCocoa 棵红。但是 RAC 依賴于 ReactiveSwift ,等于你引入了兩個庫咧栗。
如果你的項目是 swift 和 OC 混編逆甜,你需要同時引用 ReactiveCocoa 和 ReactiveObjCBridge 。但是 ReactiveObjCBridge 依賴于 ReactiveObjC 致板,所以你就等于引入了 4 個庫交煞。
ReactiveCocoa 試圖解決什么問題
- 傳統(tǒng) iOS 開發(fā)過程中,狀態(tài)以及狀態(tài)之間依賴過多的問題
- 傳統(tǒng) MVC 架構的問題:Controller 比較復雜斟或,可測試性差
- 提供統(tǒng)一的消息傳遞機制
傳統(tǒng) iOS 開發(fā)過程中素征,狀態(tài)以及狀態(tài)之間依賴過多的問題
我們在開發(fā) iOS 應用時,一個界面元素的狀態(tài)很可能受多個其它界面元素或后臺狀態(tài)的影響萝挤。
例如御毅,在用戶帳戶的登錄界面,通常會有 2 個輸入框(分別輸入帳號和密碼)和一個登錄按鈕怜珍。如果我們要加入一個限制條件:當用戶輸入完帳號和密碼端蛆,并且登錄的網絡請求還未發(fā)出時,確定按鈕才可以點擊酥泛。通常情況下今豆,我們需要監(jiān)聽這兩個輸入框的狀態(tài)變化以及登錄的網絡請求狀態(tài),然后修改另一個控件的enabled
狀態(tài)柔袁。
RAC 通過引入信號(Signal)的概念呆躲,來代替?zhèn)鹘y(tǒng) iOS 開發(fā)中對于控件狀態(tài)變化檢查的代理(delegate)模式或 target-action 模式。因為 RAC 的信號是可以組合(combine)的捶索,所以可以輕松地構造出另一個新的信號出來插掂,然后將按鈕的enabled狀態(tài)與新的信號綁定。
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并不會自動生成所有的返回值,需要根據(jù)自己在前面綁定的幾個信號自己補全,然后直到這部分代碼完全寫完中間可能一直在報錯,不要理他.從RAC的源碼中可以看出來,前面綁定的信號不同后面的block返回值類型也是不同的.
統(tǒng)一消息傳遞機制
iOS 開發(fā)中有著各種消息傳遞機制,包括 KVO辅甥、Notification箩祥、delegation、block 以及 target-action 方式肆氓。各種消息傳遞機制使得開發(fā)者在做具體選擇時感到困惑. 在引入 RAC 之后,以前散落在action-target或 KVO 的回調函數(shù)中的判斷邏輯被統(tǒng)一到了一起.
// 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 框架的問題
對于傳統(tǒng)的 Model-View-Controller 的框架底瓣,Controller 很容易變得比較龐大和復雜谢揪。由于 Controller 承擔了 Model 和 View 之間的橋梁作用,所以 Controller 常常與對應的 View 和 Model 的耦合度非常高捐凭,這同時也造成對其做單元測試非常不容易拨扶,對 iOS 工程的單元測試大多都只在一些工具類或與界面無關的邏輯類中進行。
RAC 的信號機制很容易將某一個 Model 變量的變化與界面關聯(lián)茁肠,所以非常容易應用 Model-View-ViewModel 框架患民。通過引入 ViewModel 層,然后用 RAC 將 ViewModel 與 View 關聯(lián)垦梆,View 層的變化可以直接響應 ViewModel 層的變化匹颤,這使得 Controller 變得更加簡單,由于 View 不再與 Model 綁定托猩,也增加了 View 的可重用性印蓖。
MVVM 的作用和問題
MVVM 在實際使用中,確實能夠使得 Model 層和 View 層解耦京腥,但是如果你需要實現(xiàn) MVVM 中的雙向綁定的話赦肃,那么通常就需要引入更多復雜的框架來實現(xiàn)了。
對此公浪,MVVM 的作者 John Gossman 的 批評 應該是最為中肯的他宛。John Gossman 對 MVVM 的批評主要有兩點:
第一點:數(shù)據(jù)綁定使得 Bug 很難被調試。你看到界面異常了欠气,有可能是你 View 的代碼有 Bug厅各,也可能是 Model 的代碼有問題。數(shù)據(jù)綁定使得一個位置的 Bug 被快速傳遞到別的位置晃琳,要定位原始出問題的地方就變得不那么容易了讯检。
第二點:對于過大的項目,數(shù)據(jù)綁定需要花費更多的內存卫旱。
附:
之前在上家公司用過一個MBMvc的框架來幫助分層,很好用,不過我看了一下github上已經很久沒有更新了,懷疑是不是有什么問題停更了呢, 大家有興趣的可以了解一下這個框架.