RxDataSources tableView具有来自一个API源的多个节 [英] RxDataSources tableView with multiple sections from one API source
问题描述
当前,对于我们的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屋!