首页 > 解决方案 > 如何从 BehaviorRelay observable 更新 tableView?

问题描述

我正在尝试使用油门在表格视图中进行搜索。

在这里,我在 ViewModel 中有 BehaviorRelay

var countryCodes: BehaviorRelay<[CountryDialElement]> = BehaviorRelay<[CountryDialElement]>(value:[])

在这里,我有输入文本的 BehaviorRelay

var searchText: BehaviorRelay<String> = BehaviorRelay<String>(value: "")

在这里,我有与 View Model 中的 Observable 绑定的 Table View

self.viewModel.params.countryCodes.bind(to: tableView.rx.items(cellIdentifier: "CountryDialTableViewCell")) { index, model, cell in
      let countryCell = cell as! CountryDialTableViewCell
      countryCell.configure(model)
    }.disposed(by: disposeBag)

在这里,我将 Rx 绑定到 ViewController 中的 UISearchBar

searchBar
      .rx
      .text
      .orEmpty
      .debounce(.milliseconds(300), scheduler: MainScheduler.instance)
      .distinctUntilChanged()
      .subscribe { [weak self] query in
        guard
          let query = query.element else { return }
        self?.viewModel.params.searchText.accept(query)
      }
      .disposed(by: disposeBag)

然后在 ViewModel 中,我尝试过滤数据并将过滤后的数据推送到 dataSource,以更新 tableView。

Observable.combineLatest(params.countryCodes, params.searchText) { items, query in
      return items.filter({ item in
        item.name.lowercased().contains(query.lowercased()) || item.dialCode.lowercased().contains(query.lowercased())
      })
    }.subscribe(onNext: { resultArray in
      self.params.countryCodes.accept(resultArray)
    })
    .disposed(by: disposeBag)

但我收到这种类型的错误

Reentrancy anomaly was detected.
This behavior breaks the grammar because there is overlapping between sequence events.
The observable sequence is trying to send an event before sending the previous event has finished.
Interpretation: This could mean that there is some kind of unexpected cyclic dependency in your code, or that the system is not behaving in an expected way.

我正在努力实现:

  1. 带有可观察数组的绑定表视图
  2. 在搜索栏中输入文本
  3. 过滤可观察对象,数组
  4. 更新 observable,重新加载 tableView。

标签: iosswiftrx-swift

解决方案


我注意到的第一件事......你有两个 BehaviorRelays 定义为var. 您应该始终使用 定义它们let

您没有发布足够的代码来演示该错误,但正如错误消息中向您解释的那样,根本问题是您正在破坏 observable 语法,因为您在推送数据的过程中通过 Observable 推送数据。如果允许,它将形成一个无限递归调用,该调用会溢出堆栈。

在当前事件完成发送之前不要发送事件。如果您不使用这么多继电器,那将有很大帮助...

你没有说数组中的项目来自哪里,这也很难帮助......

考虑这样的事情:

Observable.combineLatest(
    searchBar.rx.text.orEmpty
        .debounce(.milliseconds(300), scheduler: MainScheduler.instance)
        .distinctUntilChanged()
        .startWith(""),
    sourceOfItems(),
    resultSelector: { searchTerm, items in
        items.filter { $0.code.contains(searchTerm) }
    }
)
.bind(to: tableView.rx.items(cellIdentifier: "CountryDialTableViewCell")) { index, model, cell in
    let countryCell = cell as! CountryDialTableViewCell
    countryCell.configure(model)
}
.disposed(by: disposeBag)

推荐阅读