Swift RxSwift(一)

Swift RxSwift(一)

RxSwift,一个非常火的框架,基本上国内很少有企业或者公司用,一方面,毕竟现在大部分公司还是ObjC语言,而且还要支持iOS7,一下子转Swift不现实。另一方便就是RxSwift对于实际项目来说前期可能有点慢,团队开发效率慢,团队协作时要求每个人都需要理解和学习RxSwift,前期投入精力大,对成员要求高,实际中开发APP也要有进度控制。

为什么我要使用RxSwift?

因为RxSwift可以使你的整个项目的代码量减少了很多,逻辑和功能也变得更加易读和清晰。

什么是RxSwift

RxSwift是一个响应式函数式编程(Functional Reactive Programming:FRP)的框架,FRP是一种和事件流有关的编程方式,其角度类似于EventSoucing,关注导致状态值改变的行为事件,一系列事件组成的事件流。举例:a + b = c;之前iOS比较火的RAC(ReactiveCocoa),目前已经3.0,支持swift和ObjC,他们2个概念上都基本相同,看个人喜好。

RxSwift核心(Observable)

Observable也就是一个被观察的对象,是一个事件序列,可以订阅它,监测事件的发生(Next\Complete\Error)。KVO?

热信号和冷信号

最本质的区别是一个是有订阅者来订阅的时候,热信号已经触发了一些事件,那么此订阅者可能会错过一些事,冷信号则不会,冷信号是被订阅了才会发生事件,因此不会错过事件。

获取或创建Observable

Observable有2种方式

  1. 第一种是框架自带提供的,比如UITextfield,如果你要订阅text的变化,可以通过textfield.rx_text来获取Observable的对象
  2. 第二种是自己创建(Create),比如你要用到Alamofire,你想把response作为一个Observable,你可以这样写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
}
}

ps: 除了create,还可以通过never()创建一个什么都不发送的空序列,用empty()创建一个空序列但会发送.Complete等等。

信号操作

常用的操作符有map,flatMap,subscribe,doOn,retry等等,具体的用法在它的文档中有具体说明。比如你在做分页刷新数据的是偶,我们需要这样做,在UIViewController里先创建一个属性:

1
2
var page : Variable<Int> = Variable(0)

那么接下来我们要如何做呢,接下来我们需要订阅page这个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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)

这段代码里实现了在page发生变化的时候自动去请求服务端的数据,然后刷新tableview。throttle保证了事件序列发送的频率不会过快,doOn在每次.Next到来之前让我们有机会做些额外的处理,页码变化通过flatMap触发API调用,然后把得到的数据绑定到每个cell上面。