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)
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.
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.
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
.
How should this be implemented in RxDataSources? Ideally would be to bind it to the service I showed earlier (OrderRxService.....subscribe()..
).
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
}
}
What I tried to make it work is:
// 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))
}
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?
Would it be possible to have it something like:
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...
Thanks for any help!