RxDataSources tableView具有来自一个API源的多个节 [英] RxDataSources tableView with multiple sections from one API source

查看:137
本文介绍了RxDataSources tableView具有来自一个API源的多个节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前,对于我们的API请求,我们使用Rx.我们如何使用它的一个示例是:

Currently for our API requests we use Rx. An example of how we use it is:

let orderRxService = OrderRxService.listAsShop(shopId, status: .active)
    .repeatRequest(delay: 4)
    .observeOn(MainScheduler.instance)
    .subscribe( onNext: { [weak self] orders in
        self?.orders = orders
        self?.tableView.reloadData()
    })
    .disposed(by: disposeBag)

这将获取状态为 .active 的给定 shopId 的所有订单.每次更新时,都会替换本地 orders 对象,并重新加载tableView.

This gets all orders for given shopId with the status .active. On every update the local orders object is replaced and the tableView is reloaded.

这将重新加载整个tableView,我们要避免这样做.我现在正在研究RxDataSources,但无法真正弄清楚如何使它工作.

This reload the whole tableView, which we wanna avoid. I'm now looking into RxDataSources but can't really figure out what is the way to get this working.

Order 对象具有另一个属性 currentStatus ,该属性可以是3个不同的值.我们拥有的tableView具有3个不同的部分,每个部分显示 currentStatus 的所有订单.

An Order object has another property currentStatus, which can be 3 different values. What we have is a tableView with 3 different sections, each section displaying all orders for a currentStatus.

该如何在RxDataSources中实现?理想情况是将其绑定到我先前显示的服务( OrderRxService ..... subscribe().. ).

How should this be implemented in RxDataSources? Ideally would be to bind it to the service I showed earlier (OrderRxService.....subscribe()..).

我现在要设置RxDataSources类型是:

What I have now to setup the RxDataSources-types is:

extension Order: IdentifiableType, Equatable {
    public typealias Identity = String

    public var identity: String {
        return String(id)
    }

    public static func == (lhs: Order, rhs: Order) -> Bool {
        return (lhs.timeCreated ?? 0) > (rhs.timeCreated ?? 0)
    }
}

struct OrdersSection {
    var header: String
    var orders: [Order]
}

extension OrdersSection: AnimatableSectionModelType {
    typealias Item = Order
    typealias Identity = String

    var identity: String {
        return header
    }

    var items: [Item] {
        set {
            orders = items
        }
        get {
            return orders
        }
    }

    init(original: OrdersSection, items: [Order]) {
        self = original
        self.items = items
    }
}

我试图使其工作的是:

// I tried to make our local orders a Variable (I don't like this between-step and would like this to be just [Order]).
var orders: Variable<[Order]> = Variable([])


fun viewDidLoad() {
    super.viewDidLoad()

    // Then I set the local orders-variable's value to the new value coming from our Rx service.
    let orderRxDisposable: Disposable = OrderRxService.listAsShop(shopId, status: .active)
        .repeatRequest(delay: 4)
        .observeOn(MainScheduler.instance)
        .map { $0.items }.subscribe( onNext: { [weak self] orders in
            self?.orders.value = orders
        })

    // Here I setup the dataSource
    let dataSource = RxTableViewSectionedAnimatedDataSource<OrdersSection>(
        configureCell: { ds, tv, ip, item in
            let cell = tv.dequeueReusableCell(withIdentifier: "OrderCell", for: ip) as! OrderCell
            cell.addContent(item, tableView: tv, viewController: self, spotDelegate: self)
            return cell
        },

        titleForHeaderInSection: { ds, ip in
            return ds.sectionModels[ip].header
        }
    )

    // Here I set up the three different sections.
    self.orders.asObservable().observeOn(MainScheduler.instance)
        .map { o in
            o.filter { $0.currentStatus == .status_one }
        }
        .map { [OrdersSection(header: "Status one", orders: $0)] }
        .bind(to: self.tableView.rx.items(dataSource: dataSource))

    self.orders.asObservable().observeOn(MainScheduler.instance)
        .map { o in
            o.filter { $0.currentStatus == .status_two }
        }
        .map { [OrdersSection(header: "Status two", orders: $0)] }
        .bind(to: self.tableView.rx.items(dataSource: dataSource))

    self.orders.asObservable().observeOn(MainScheduler.instance)
        .map { o in
            o.filter { $0.currentStatus == .status_three }
        }
        .map { [OrdersSection(header: "Status three", orders: $0)] }
        .bind(to: self.tableView.rx.items(dataSource: dataSource))

}

可能有不同方面可以改进.例如, Variable< [Order]> 我只是想成为 [Order] .除了观察到这一点之外,还可以通过观察我们的OrderRxService完全跳过并创建三个不同的部分吗?

There are probably different aspects that can be improved. For example the Variable<[Order]> I would like to be just [Order]. And instead of making this observable, could that be skipped altogether and create the three different sections by observing our OrderRxService?

是否有可能像这样:

OrderRxService.listAsshop(shopId, status: .active).observeOn(MainScheduler.instance)
    // First section
    .map { o in
        o.filter { $0.status == .status_one }
    }
    .map { [OrdersSection(header: "Status one", orders: $0)] }
    .bind(to: self.tableView.rx.items(dataSource: dataSource))
    // Second section
    .map { o in
        o.filter { $0.status == .status_two }
    }
    .map { [OrdersSection(header: "Status two", orders: $0)] }
    .bind(to: self.tableView.rx.items(dataSource: dataSource))
    // Etc...

感谢您的帮助!

推荐答案

您可以像这样创建模型:

You could create a model like so:

enum SectionModel {
  case SectionOne(items: [SectionItem])
  case SectionTwo(items: [SectionItem])
  case SectionThree(items: [SectionItem])
}

enum SectionItem {
  case StatusOne()
  case StatusTwo()
  case StatusThree()
}

extension SectionModel: SectionModelType {
  typealias Item = SectionItem

  var items: [SectionItem] {
      switch self {
      case .SectionOne(items: let items):
          return items.map { $0 }
      case .SectionTwo(items: let items):
          return items.map { $0 }
      case.SectionThree(items: let items):
          return items.map { $0 }
      }
  }

  init(original: SectionModel, items: [Item]) {
      switch  original {
      case .SectionOne(items: _):
          self = .SectionOne(items: items)
      case .SectionTwo(items: _):
          self = .SectionTwo(items: items)
      case .SectionThree(items: _):
          self = .SectionThree(items: items)
      }
  }
}

并处理数据源中的不同项目

and handle the different items in your datasource

dataSource = RxCollectionViewSectionedReloadDataSource<SectionModel>(configureCell: { (datasource, collectionView, indexPath, _) in
        switch datasource[indexPath] {
        case .StatusOne:
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: R.reuseIdentifier.statusCellOne, for: indexPath)!
            // do stuff
            return cell
        case .StatusTwo:
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: R.reuseIdentifier.statusCellTwo, for: indexPath)!
            // do stuff
            return cell
        case .StatusThree:
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: R.reuseIdentifier.statusCellThree, for: indexPath)!
            // do stuff
            return cell
        }
    })

,然后将您的订单映射到 SectionModel SectionItem 并将其绑定到dataSource

and then map your oders to the SectionItem for the SectionModel and bind it to the dataSource

这篇关于RxDataSources tableView具有来自一个API源的多个节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆