最近開始研究RxSwift,網(wǎng)上能查到的資料太有限,邊學(xué)邊記錄,有不對的地方歡迎大家指正。
按照官方自己的說法,它是swift版本的Rx,是一個提供響應(yīng)函數(shù)式編程的框架。之前在iOS開發(fā)領(lǐng)域比較火的ReactiveCocoa也是根據(jù)Rx來的,所以在概念上基本是相同的。在GitHub上把代碼取下來之后,運行官方的Demo可以看到它的很多用法。關(guān)于其中涉及到的核心概念在它的playground里也有很詳細(xì)的說明。
Observable
Observable也就是一個被觀察的對象,是一個事件序列,訂閱者可以訂閱它,監(jiān)測事件的發(fā)生(Next\Complete\Error)。是不是聽到這里就感覺這貨有點像KVO?
熱信號vs冷信號
信號分兩種,熱信號在它創(chuàng)建的時候就開始推送事件,這意味著如果后面有訂閱者來的時候,就可能會錯過一些事件。而冷信號則不會,只有在它被訂閱的時候,它才會發(fā)送事件,這可以保證后面即使有訂閱者中途加入的時候也能收到完整的事件序列。
獲得Observable
要得到一個Observable有兩種方式,一種是RxSwift已經(jīng)提供了的(這里你可能需要引入RxCocoa),一種是自己創(chuàng)建。比如你有一個UITextfield,你要訂閱其text的變化,就可以通過textfield.rx_text來獲得這個Observable<String>的對象。如果要自己創(chuàng)建的話,可以利用它提供的create函數(shù)來創(chuàng)建,create接受函數(shù)閉包作為參數(shù),比如我的項目里用到了Alamofire,我如果想讓它的response是一個observable的,我可以這樣寫:
func fetchClubList(fromPage page:Int) -> Observable<[ClubTableCellViewModel]>{
return create{ (observer ) -> Disposable in
Alamofire.request(Method.GET, "http://www.mocky.io/v2/560a046995e00cc208981280").responseArray{[unowned self]
(results:[ClubModel]?, err:ErrorType?) -> Void in
if let _ = err{
observer.on(Event.Error(err!))
}else{
if let cellVMs = (results?.map{ClubTableCellViewModel(club: $0)}){
if page == 0{
self.cellViewModels.removeAll()
}
self.cellViewModels.appendContentsOf(cellVMs)
observer.on(Event.Next(self.cellViewModels))
observer.on(Event.Completed)
}else{
//TODO: error handle
}
}
}
return NopDisposable.instance
}
}
這樣就創(chuàng)建了一個Observable<[ClubModel]>,當(dāng)他上面有事件發(fā)生的時候,我們可以做相應(yīng)的操作。除了create,還可以通過never()創(chuàng)建一個什么都不發(fā)送的空序列,用empty()創(chuàng)建一個空序列但會發(fā)送.Complete等等。
信號的操作
常用的操作符有map,flatMap,subscribe,doOn,retry等等,具體的用法在它的文檔中有具體說明。比如在我的demo里,需要根據(jù)頁碼加載列表數(shù)據(jù)。可以像這樣做,在我的UIViewController里先創(chuàng)建一個屬性:
var page : Variable<Int> = Variable(0)
接下來訂閱這個page
self.page
.throttle(0.5, MainScheduler.sharedInstance)
.doOn{ [unowned self] value in
self.refreshCtrl.enabled = false
}
.flatMap {[unowned self] in
self.viewModel.fetchClubList(fromPage: $0)
.doOn{ [unowned self] in
self.refreshCtrl.endRefreshing()
self.refreshCtrl.enabled = true
}
.retry()
.catchErrorJustReturn([])
}
.bindTo(self.clubList.rx_itemsWithCellIdentifier("clubCell")){(_, viewModel, cell: ClubListCell) in
cell.viewModel = viewModel
}
.addDisposableTo(self.dispose)
這段代碼里實現(xiàn)了在page發(fā)生變化的時候自動去請求服務(wù)端的數(shù)據(jù),然后刷新tableview。throttle保證了事件序列發(fā)送的頻率不會過快,doOn在每次.Next到來之前讓我們有機會做些額外的處理,頁碼變化通過flatMap觸發(fā)API調(diào)用,然后把得到的數(shù)據(jù)綁定到每個cell上面。
通過RxSwift整個代碼量減少了很多,也變得更加易讀,是不是感覺很棒!現(xiàn)在了解的也不夠多,歡迎大家一起來交流
參考鏈接:
http://reactivex.io/