函数响应式编程框架RxSwift 学习——Observable

2018-08-20 17:07:13 浏览数 (1)

最近开始研究RxSwift,网上能查到的资料太有限,边学边记录,有不对的地方欢迎大家指正。

按照官方自己的说法,它是swift版本的Rx,是一个提供响应函数式编程的框架。之前在iOS开发领域比较火的ReactiveCocoa也是根据Rx来的,所以在概念上基本是相同的。在GitHub上把代码取下来之后,运行官方的Demo可以看到它的很多用法。关于其中涉及到的核心概念在它的playground里也有很详细的说明。


Observable

Observable也就是一个被观察的对象,是一个事件序列,订阅者可以订阅它,监测事件的发生(NextCompleteError)。是不是听到这里就感觉这货有点像KVO?

热信号vs冷信号

信号分两种,热信号在它创建的时候就开始推送事件,这意味着如果后面有订阅者来的时候,就可能会错过一些事件。而冷信号则不会,只有在它被订阅的时候,它才会发送事件,这可以保证后面即使有订阅者中途加入的时候也能收到完整的事件序列。

获得Observable

要得到一个Observable有两种方式,一种是RxSwift已经提供了的(这里你可能需要引入RxCocoa),一种是自己创建。比如你有一个UITextfield,你要订阅其text的变化,就可以通过textfield.rx_text来获得这个Observable<String>的对象。如果要自己创建的话,可以利用它提供的create函数来创建,create接受函数闭包作为参数,比如我的项目里用到了Alamofire,我如果想让它的response是一个observable的,我可以这样写:

代码语言:javascript复制
    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
        }
    }

这样就创建了一个Observable<[ClubModel]>,当他上面有事件发生的时候,我们可以做相应的操作。除了create,还可以通过never()创建一个什么都不发送的空序列,用empty()创建一个空序列但会发送.Complete等等。

信号的操作

常用的操作符有map,flatMap,subscribe,doOn,retry等等,具体的用法在它的文档中有具体说明。比如在我的demo里,需要根据页码加载列表数据。可以像这样做,在我的UIViewController里先创建一个属性:

代码语言:javascript复制
    var page : Variable<Int> = Variable(0)

接下来订阅这个page

代码语言:javascript复制
        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上面。

通过RxSwift整个代码量减少了很多,也变得更加易读,是不是感觉很棒!现在了解的也不够多,欢迎大家一起来交流

参考链接: http://reactivex.io/

0 人点赞