RxSwift-MVVM双向绑定

1,504

RxSwift篇章

案例

  • 输入框搜索 - 请求网络 - tableView联动

VC代码

        //搜索框绑定到viewModel的搜索序列上去
        self.searchBar.rx.text.orEmpty
            .bind(to: self.viewModel.searchTextOB)
            .disposed(by: disposebag)
        //搜索数据绑定到tableView
        self.viewModel.searchData.drive(self.tableView.rx.items){ (tb,indexPath,model) -> PLTableViewCell in
            let cell = tb.dequeueReusableCell(withIdentifier: "PLTableViewCell") as! PLTableViewCell
            cell.setData(model)
            cell.selectionStyle = .none
            return cell
        }.disposed(by: self.disposebag)
        //统计搜索数据
        self.viewModel.searchData
            .map { (array) -> String in
            return "搜到了\(array.count)个"
            }
            .drive(self.navigationItem.rx.title)
            .disposed(by: disposebag)
  • RxSwift世界里的ViewController内, 建立View与ViewModel之间的绑定依赖关系.
  • 通过我们搜索栏的响应,发送数据给我们的ViewModel,让它内部处理业务层,最后返回数据.

模型代码

class PLComprehensiveViewModel: NSObject {
    // 搜索关键字序列
    let searchTextOB = BehaviorSubject(value: "")
    // 搜索数据
    lazy var searchData: Driver<[PLReposityModel]> = {
        // 利用输入框序列
        return self.searchTextOB.asObservable()
            .throttle(RxTimeInterval.milliseconds(300), scheduler: MainScheduler.instance)
            .distinctUntilChanged()
            .flatMapLatest(PLComprehensiveViewModel.responseData)
            .asDriver(onErrorJustReturn: [])
    }()
    ...
}
  • 搜索searchTextOB关联了输入框的变化.

  • 搜索数据序列searchData通过throttle保证了相隔0.3秒发送一次事件

  • distinctUntilChanged函数保证了带宽,直到搜索关键字变动的时候才请求

  • flatMapLates因为序列的序列,我们下沉请求

  • asDriver包装成Drive序列,保证状态共享,主线程调度,没有错误返回

   /// 数据请求
    static func responseData(_ githubID: String) -> Observable<[PLReposityModel]> {
        guard !githubID.isEmpty,let url = URL(string: "https://api.github.com/users/\(githubID)/repos") else {
            return Observable.just([])
        }
        return URLSession.shared.rx.json(url: url)
            .retry()
            .observeOn(ConcurrentDispatchQueueScheduler(qos: .background))
            .map(PLComprehensiveViewModel.dataParse)
    }
  • 通过上面的响应,这里封装网络URLSession.shared.rx.json,返回json

  • 为了保证请求网络在子线程,这里调用observeOn

  • 请求回来的数据还不是我们所想要的,通过map映射序列化结果

    /// 数据序列化
    static func dataParse(_ json:Any) -> [PLReposityModel]{
        /// 字典数组
        guard let items = json as? [[String:Any]] else { return [] }
        /// 模型化
        guard let result =  [PLReposityModel].deserialize(from: items) as? [PLReposityModel] else{
            return []
        }
        return result
    }
  • 通过HandJSON进行数据解析

  • 返回的结果序列成模型数组

总结

  • VC轻量化
  • MVVM与RxSwift的结合很安逸