Обновление RxSwift tableView на основе свойства - PullRequest
0 голосов
/ 24 января 2019

У меня есть UITableView, заполненный моделями продуктов. У меня есть 2 проблемы прямо сейчас. Во-первых, у меня есть количествоLabel в ячейках, которое я хочу обновить, когда пользователь нажимает кнопку увеличения или уменьшения в ячейке. В настоящее время для этого я обновляю модель и принимаю совершенно новый массив, который вызывает перезагрузку tableView, что не идеально. Вторая проблема заключается в том, что, когда количество Продукта становится равным 0, эта ячейка должна быть удалена из tableView с анимацией. В настоящее время я просто нахожу индекс продукта в источнике данных, удаляю его и перезагружаю таблицу. Я хотел бы знать правильный способ Rx сделать это. Вот пример моего кода. Спасибо!

struct Product: Equatable {
  var i: String
  var quantity: Int
  init(i: Int, quantity: Int) {
    self.i = "item: \(i)"
    self.quantity = quantity
  }
}
extension Product {
  static func ==(lhs: Product, rhs: Product) -> Bool {
    return lhs.i == rhs.i
  }
}

class ProductSource {
  var items: BehaviorRelay<[Product]> = BehaviorRelay<[Product]>(value: [])
  var itemsObservable: Observable<[Product]>
  init() {
    itemsObservable = items.asObservable().share(replay: 1)
    items.accept((0..<20).map { Product(i: $0, quantity: 2) })
  }

  func add(product: Product) {}

  func remove(product: Product) {
    guard let index = self.items.value.index(of: product) else {return}

  // decrement quantity, if quantity is 0, remove from the datasource and update the tableView
  }
}

class ViewController: UIViewController {

  @IBOutlet weak var tableView: UITableView!
  var disposeBag = DisposeBag()
  var data = ProductSource()

  override func viewDidLoad() {
    super.viewDidLoad()

    tableView.rx.setDelegate(self).disposed(by: disposeBag)
    data.itemsObservable
        .bind(to: tableView.rx.items(cellIdentifier: "productCell", cellType: ProductTableViewCell.self)) { row, element, cell in
            cell.nameLabel.text = element.i
            cell.quantityLabel.text = String(element.quantity)
    }.disposed(by: disposeBag)
  }
}

extension ViewController: UITableViewDelegate {
  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 100
  }
}

1 Ответ

0 голосов
/ 25 января 2019

Обе ваши проблемы могут быть решены с помощью RxDataSources Cocoapod.

В качестве альтернативы, вы можете бросить свой собственный, как я сделал здесь: https://github.com/dtartaglia/RxMultiCounter/blob/master/RxMultiCounter/RxExtensions/RxSimpleAnimatableDataSource.swift

Идея в том, чтобы использовать что-то (я использую DifferenceKit), чтобы выяснить, какие элементы изменились, и перезагрузить только эти конкретные элементы. Для этого вам нужен специализированный объект источника данных, а не общий, который поставляется с RxCocoa.

...