I am trying to make multiple sections (two actually) using RxDatasources. Usually with one section, I would go like this:
Section model:
import Foundation
import RxDataSources
typealias NotificationSectionModel = AnimatableSectionModel<String, NotificationCellModel>
struct NotificationCellModel : Equatable, IdentifiableType {
static func == (lhs: NotificationCellModel, rhs: NotificationCellModel) -> Bool {
return lhs.model.id == rhs.model.id
}
var identity: String {
return model.id
}
var model: NotificationModel
var cellIdentifier = "NotificationTableViewCell"
}
then the actual model:
struct NotificationModel: Codable, Equatable {
let body: String
let title:String
let id:String
}
And I would use that like this (in view controler):
private func observeTableView(){
let dataSource = RxTableViewSectionedAnimatedDataSource<NotificationSectionModel>(
configureCell: { dataSource, tableView, indexPath, item in
if let cell = tableView.dequeueReusableCell(withIdentifier: item.cellIdentifier, for: indexPath) as? BaseTableViewCell{
cell.setup(data: item.model)
return cell
}
return UITableViewCell()
})
notificationsViewModel.notifications
.map{ notifications -> [NotificationCellModel] in
return notifications.map{ NotificationCellModel( model: $0, cellIdentifier: NotificationTableViewCell.identifier) }
}.map{ [NotificationSectionModel(model: "", items: $0)] }
.bind(to: self.tableView.rx.items(dataSource: dataSource)).disposed(by: disposeBag)
}
But how I would go with multiple sections, with different type of models/cells?
CodePudding user response:
Here is a kind of worst case situation. You might be able to simplify this code depending on your use case:
// MARK: Model Code
struct ViewModel {
let sections: Observable<[SectionModel]>
}
typealias SectionModel = AnimatableSectionModel<String, CellModel>
enum CellModel: IdentifiableType, Equatable {
case typeA(TypeAInfo)
case typeB(TypeBInfo)
var identity: Int {
switch self {
case let .typeA(value):
return value.identity
case let .typeB(value):
return value.identity
}
}
var cellIdentifier: String {
switch self {
case .typeA:
return "TypeA"
case .typeB:
return "TypeB"
}
}
}
struct TypeAInfo: IdentifiableType, Equatable {
let identity: Int
}
struct TypeBInfo: IdentifiableType, Equatable {
let identity: Int
}
// MARK: View Code
class Example: UIViewController {
var tableView: UITableView!
var viewModel: ViewModel!
let disposeBag = DisposeBag()
private func observeTableView(){
let dataSource = RxTableViewSectionedAnimatedDataSource<SectionModel>(
configureCell: { _, tableView, indexPath, item in
guard let cell = tableView.dequeueReusableCell(withIdentifier: item.cellIdentifier, for: indexPath) as? BaseCell else { fatalError() }
cell.setup(model: item)
return cell
})
viewModel.sections
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
}
}
class BaseCell: UITableViewCell {
func setup(model: CellModel) { }
}
final class TypeACell: BaseCell { }
final class TypeBCell: BaseCell { }