使用 RxDataSource 绑定到 TableView。在我看来这是最好的。
我给你发了代码,它使用了集合视图,但在 Rx 中的表格视图将是相同的实现。
https://github.com/RxSwiftCommunity/RxDataSources
这里是例子:
视图模型:
extension ModelListViewModel {
enum Sections: SectionModelType, Equatable {
static func == (lhs: ModelListViewModel.Sections, rhs: ModelListViewModel.Sections) -> Bool {
switch (lhs, rhs) {
case (.model(let lItem), .model(let rItem)):
return lItem == rItem
}
}
typealias Item = Asset
case model(models: [Item])
var items: [Item] {
switch self {
case .model(let models):
return models
}
}
init(original: Sections, items: [Item]) {
self = original
}
}
}
class ModelListViewModel {
//inputs
let didLoad = PublishSubject<Void>()
let modelSelected = PublishSubject<Asset>()
//outputs
let sections: Driver<[Sections]>
private let disposeBag = DisposeBag()
private static var data: [ModelDTO] = {
var array = [ModelDTO]()
let firstModel = ModelDTO(url: ModelDTO.seatModel(), img: #imageLiteral(resourceName: "seat"), modelName: "Seat")
let secondModel = ModelDTO(url: ModelDTO.big_910_Model(), img: #imageLiteral(resourceName: "910_big"), modelName: "Big_910")
let thirdModel = ModelDTO(url: ModelDTO.big_730_Model(), img: #imageLiteral(resourceName: "730_big"), modelName: "Big_730")
let fourthModel = ModelDTO(url: ModelDTO.small_730_Model(), img: #imageLiteral(resourceName: "910_small"), modelName: "Small_730")
let fifthModel = ModelDTO(url: ModelDTO.normal_730_Model(), img: #imageLiteral(resourceName: "910_normal"), modelName: "Normal_730")
let sixthModel = ModelDTO(url: ModelDTO.butcherSmallModel(), img: #imageLiteral(resourceName: "butcher_small"), modelName: "Butcher_Small")
let seventhModel = ModelDTO(url: ModelDTO.butcherBigModel(), img: #imageLiteral(resourceName: "butcher_big"), modelName: "Butcher_Big")
return [firstModel, secondModel, thirdModel, fourthModel, fifthModel, sixthModel, seventhModel]
}()
init(context: ARRouter.ModelListContext, modelsEntity: ModelsEntity) {
//TODO: Make sections due to responce from BackEnd
sections = didLoad
.mapTo([Sections.model(models: ModelListViewModel.data)])
.asDriver(onErrorDriveWith: .empty())
modelSelected.map { $0.model.url }
.unwrap()
.bind(to: context.modelSelectedIn)
.disposed(by: disposeBag)
}
}
和ViewController:
class ModelListViewController: BaseViewController {
private struct Cells {
static let modelListCell = ReusableCell<ModelListCell>(nibName: "ModelListCell")
}
@IBOutlet private weak var collectionView: UICollectionView! {
didSet {
collectionView.register(Cells.modelListCell)
viewModel.sections
.drive(collectionView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
collectionView.rx
.modelSelected(Asset.self)
.bind(to: viewModel.modelSelected)
.disposed(by: disposeBag)
}
}
private let disposeBag = DisposeBag()
private let viewModel: ModelListViewModel
private let dataSource: RxCollectionViewSectionedReloadDataSource<ModelListViewModel.Sections>
init(viewModel: ModelListViewModel) {
self.viewModel = viewModel
self.dataSource = .init(configureCell: { (_, tableView, indexPath, item) -> UICollectionViewCell in
let cell = tableView.dequeue(Cells.modelListCell, for: indexPath)
cell.setupCell(with: item)
return cell
})
super.init(nibName: "ModelListViewController", bundle: nil)
rx.viewDidLoad
.bind(to: viewModel.didLoad)
.disposed(by: disposeBag)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = true
title = "Models"
}
}
我给你发送了如何使用它的好例子:)
享受吧。