关于 RxSwift/RxCocoa 与 combineLatest 绑定的问题

Posted

技术标签:

【中文标题】关于 RxSwift/RxCocoa 与 combineLatest 绑定的问题【英文标题】:Question about RxSwift/RxCocoa binding with combineLatest 【发布时间】:2020-12-20 04:56:12 【问题描述】:

下面是一个简单的例子,将viewModel的字符串数组绑定到UITableView。

我想再订阅一个 viewModel.randomString 并在单元格中使用它。 我尝试如下使用 combineLatest,但我当然无法绑定到 tableview。 您对如何实现它有任何想法吗?

class SimpleViewModel 
    var list = BehaviorRelay<[String]>(value: [])
    var randomString = BehaviorRelay<String>(value: "")
    
    func fetch() 
        // Request...
        list.accept(["result1", "result2", "result3"])
        randomString.accept("Random...")
    


class SimpleViewController 
    let tableView = UITableView()
    let viewModel = ViewModel()
    
    func foo() 
        // It works well.
        viewModel.list.bind(to: tableView.rx.items(cellIdentifier: "Cell"))  (index, element, cell) in
            cell.textLabel?.text = element
        
        
        // I want to bind the viewModel.list to the tableView and use the viewModel.randomString string together.
        Observable.combineLatest(viewModel.list, viewModel.randomString)
        // How???
//            .bind(to: tableView.rx.items(cellIdentifier: "Cell"))  (index, element, cell) in
//                cell.textLabel?.text = element + "RandomString" // I want to use the "RandomString" of viewModel.randomString
//            
    

【问题讨论】:

【参考方案1】:

您的combineLatest 调用会产生一个Observable&lt;([String], String)&gt;,但为了绑定到表格视图项,您需要一个Sequence 的可观察对象。

([String], String) 不是一个序列。这是一对东西。您需要找到一种方法将其转换为一系列事物。由于您希望每个单元格都使用相同的 randomString,因此您可以使用如下函数:

 (list, randomString) in list.map  (element: $0, randomString: randomString)  

将其转换为[(String, String)],数组中每对中的第二个字符串为randomString

如果只是将上述函数传递给Observable.map,则可以将Observable&lt;([String], String)&gt; 转换为Observable&lt;[(String, String)]&gt;

Observable.combineLatest(viewModel.list, viewModel.randomString)
    .map  (list, randomString) in list.map  (element: $0, randomString: randomString)  
    .bind(to: tableView.rx.items(cellIdentifier: "cell")) 
        (index, model, cell) in
        cell.textLabel?.text = model.element + model.randomString
    .disposed(by: disposeBag)

【讨论】:

在这种特殊情况下,您可以先使用 list, random in list.map $0 + random ,然后再使用cell.textLabel?.text = element,但您的答案是更通用的解决方案。

以上是关于关于 RxSwift/RxCocoa 与 combineLatest 绑定的问题的主要内容,如果未能解决你的问题,请参考以下文章

RxSwift、RxCocoa 和 UITableview

处理 UITableView 绑定中的连接错误(Moya、RxSwift、RxCocoa)

Swft3 (RxSwift, RxCocoa) - TableView 使用响应式编程展开和折叠概念

使用 RxSwift/RxCocoa 制作的 TableView 在绑定到的变量中的数据更改后出现故障

使用 RxCocoa 时 XCode 在部署到模拟器时崩溃

RxSwift + canMoveRowAt