Swift UIKit Joint - 如何在处理发布者事件时重新加载表格视图?

Nob*_*adi 1 mvvm uikit tableview swift combine

使用组合和 UIKit,当 viewModel 中包含的数组发生更改时,我尝试更新我的表视图。我的表视图的数据源是单独的,因为我想重用该文件(不同的对象都有一个名称 var,因此表视图将显示名称列表)。

视图模型:

class ViewModel {
  @Published var items = [ItemViewModel]()
  let service = NetworkService()

  init() {
    fetchItems()
  }
    
  func fetchItems() {
    service.fetchItems { items in {
    self.items = items.map { ItemViewModel($0) }
  }
}
Run Code Online (Sandbox Code Playgroud)

数据源:

class GenericDataSource: UITableViewDataSource {
   var list = [String]()

   func setList(_ list: [String]) {
       self.list = list
   }

  // then the usual tableView datasource boilerplate
}
Run Code Online (Sandbox Code Playgroud)

视图控制器:

class ViewController: UIViewController {
  let viewModel = ViewModel()
  let tableDataSouce = GenericDataSource()
  var subscriptions = Set<AnyCancellable>()

  func setupBinding() {
    // I want to: 1) map over viewModel.$items to get [item.name]
    //            2) assign the list of names to tableDataSource.list
    //            3) reload the tableview so the new values are displayed
  }
Run Code Online (Sandbox Code Playgroud)

我不确定要使用什么组合功能。我当前(工作)代码如下:

func setupBinding() {
     viewModel.$items.handleEvents(receiveOutput: { [weak self] items in
         self?.dataSource.setList(items.map { $0.name })
         
            // dispatch called because I get yelled at for not being on main thread
            DispatchQueue.main.async { 
                 self?.itemsTableView.reloadData()
            }
        })
           .sink { _ in }
           .store(in: &subscriptions)
 }
Run Code Online (Sandbox Code Playgroud)

它有效,但我觉得我是在暴力强迫它。是否有更清晰的方法来执行与当前设置的绑定?

是否有更清晰的方法来设置代码,以便绑定更容易?

New*_*Dev 8

“更清洁”是主观的,但更“组合”的方式是:

viewModel.$items
   .receive(on: DispatchQueue.main)
   .sink { [weak self] items in
      self?.dataSource.setList(items.map(\.name))
      self?.itemsTableView.reloadData()
   }
   .store(in: &subscriptions)

Run Code Online (Sandbox Code Playgroud)

您还可以使用.map运算符来获取名称数组:

.map { $0.map(\.name) }
// ...
.sink { [weak self] names in
// ...
}
Run Code Online (Sandbox Code Playgroud)

但我认为这是一个品味问题。