首页 > 解决方案 > Observable.CombineLatest 绑定和订阅 RxSwift

问题描述

我正在开发一个使用有一些不一致的 API 的应用程序,我已经通过执行一些共享操作的这 2 个 observables 取得了结果,但第一个 ' servers ' 是一个绑定到 UITableView 的数组。

    serversViewModel.servers
        .asObservable()
        .observeOn(MainScheduler.instance)
        .bind(to: serversTableView.rx.items(cellIdentifier: ServersTableViewCell.identifier, cellType: ServersTableViewCell.self)) { [weak self] (row, element, cell) in

            guard let strongSelf = self else { return }
            cell.serverProxy.accept(element)
            if let currentServer = strongSelf.serversViewModel.currentServer.value,
                element == currentServer,
                let index = strongSelf.serversViewModel.servers.value.firstIndex(where: { $0 == currentServer }){

                strongSelf.serversTableView.selectRow(at: IndexPath(row: index, section: 0), animated: true, scrollPosition: .top)

            }

        }
        .disposed(by: disposeBag)

    serversViewModel.currentServer
        .asObservable()
        .observeOn(MainScheduler.instance)
        .subscribe(onNext: { [weak self] (server) in

            guard let strongSelf = self else { return }
            if let server = server, let index = strongSelf.serversViewModel.servers.value.firstIndex(where: { $0 == server }){
                strongSelf.serversTableView.selectRow(at: IndexPath(row: index, section: 0), animated: true, scrollPosition: .top)
            }
            else{
                strongSelf.serversTableView.deselectAllItems(animated: false)
            }

        })
        .disposed(by: disposeBag)

是否可以为两者创建一个组合的 observable 并将其用于绑定 UITableView?

谢谢

标签: rx-swift

解决方案


你想用combineLatest. 请注意,其中大部分实际上应该在您的视图模型中......

在下面的代码中,servers常量是应该显示的服务器对象数组和当前服务器的索引路径的元组。每当任何一个发出新值时,servers都会发出一个值。

以后你可能会发现以下文章对你有帮助:Recipes for Combining Observables in RxSwift

let servers = Observable.combineLatest(serversViewModel.servers, serversViewModel.currentServer) { (servers, server) -> ([Server], IndexPath?) in
    let indexPath = server.flatMap { servers.firstIndex(of: $0) }
        .map { IndexPath(row: $0, section: 0) }
    return (servers, indexPath)
}

servers
    .map { $0.0 }
    .bind(to: serversTableView.rx.items(cellIdentifier: ServersTableViewCell.identifier, cellType: ServersTableViewCell.self)) { (row, element, cell) in
        cell.serverProxy.accept(element)
    }
    .disposed(by: disposeBag)

servers
    .map { $0.1 }
    .bind(onNext: { [serversTableView] indexPath in
        if let indexPath = indexPath {
            serversTableView.selectRow(at: indexPath, animated: true, scrollPosition: .top)
        }
        else {
            serversTableView.deselectAllItems(animated: false)
        }
    })
    .disposed(by: disposeBag)

推荐阅读