J'utilise RxDatasources
pour créer ma source de données. Plus tard, je configure les cellules dans mon contrôleur de vue. Le problème est que les headers/footers n'ont rien à voir avec la source de données (sauf que nous pouvons définir un titre, mais si nous utilisons un header footer personnalisé, ce titre sera remplacé).
Voici comment je configure les cellules de mon tableau :
private func observeDatasource(){
let dataSource = RxTableViewSectionedAnimatedDataSource<ConfigStatusSectionModel>(
configureCell: { dataSource, tableView, indexPath, item in
if let cell = tableView.dequeueReusableCell(withIdentifier: ConfigItemTableViewCell.identifier, for: indexPath) as? BaseTableViewCell{
cell.setup(data: item.model)
return cell
}
return UITableViewCell()
})
botConfigViewModel.sections
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
}
cause actuelle
dataSource.titleForHeaderInSection = { dataSource, index in
return dataSource.sectionModels[index].model
}
... ne fonctionnera pas, car je veux charger un en-tête personnalisé et le remplir avec des données provenant de RxDatasource
Je me demande quelle serait la bonne façon de procéder :
- obtenir des données de ma source de données qui est définie dans mon modèle de vue
- remplir l'en-tête, basé sur une section (j'ai plusieurs sections) avec des données correctes, d'une manière qui est toujours à jour avec une source de données.
Voici mon modèle de vue :
class ConfigViewModel{
private let disposeBag = DisposeBag()
let sections:BehaviorSubject<[ConfigStatusSectionModel]> = BehaviorSubject(value: [])
func startObserving(){
let observable = getDefaults()
observable.map { conditions -> [ConfigStatusSectionModel] in
return self.createDatasource(with: conditions)
}.bind(to: self.sections).disposed(by: disposeBag)
}
private func getDefaults()->Observable<ConfigDefaultConditionsModel> {
return Observable.create { observer in
FirebaseManager.shared.getConfigDefaults { conditions in
observer.onNext(conditions!)
} failure: { error in
observer.onError(error!)
}
return Disposables.create()
}
}
private func createDatasource(with defaults:ConfigDefaultConditionsModel)->[ConfigStatusSectionModel]{
let firstSectionItems = defaults.start.elements.map{ConfigItemModel(item: $0, data: nil)}
let firstSection = ConfigStatusSectionModel(model: defaults.start.title, items: firstSectionItems.compactMap{ConfigCellModel(model: $0)})
let secondSectionItems = defaults.stop.elements.map{ConfigItemModel(item: $0, data: nil)}
let secondSection = ConfigStatusSectionModel(model: defaults.stop.title, items: secondSectionItems.compactMap{ConfigCellModel(model: $0)})
let sections:[ConfigStatusSectionModel] = [firstSection, secondSection]
return sections
}
}
Ce que j'ai pu faire, c'est définir un délégué tableview, comme ceci :
tableView.rx.setDelegate(self).disposed(by: disposeBag)
puis de mettre en œuvre la ou les méthodes déléguées appropriées pour créer / renvoyer l'en-tête personnalisé :
extension BotConfigViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView,
viewForHeaderInSection section: Int) -> UIView? {
guard let header = tableView.dequeueReusableHeaderFooterView(
withIdentifier: ConfigSectionTableViewHeader.identifier)
as? ConfigSectionTableViewHeader
else {
return nil
}
return header
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
return 40
}
}
Comment remplir mon en-tête personnalisé avec des données provenant de ma source de données ? Je ne veux pas faire des choses comme switch (section){...}
En effet, il n'est pas synchronisé avec une source de données, mais plutôt manuellement, et si la source de données change, cela n'affectera pas la configuration de l'en-tête automatiquement.
Voici les structures de mon modèle :
typealias ConfigStatusSectionModel = AnimatableSectionModel<String, ConfigCellModel>
struct ConfigItemData {
let conditionsLink:String?
let iconPath:String?
}
struct ConfigItemModel {
let item:OrderConditionModel
let data:ConfigItemData?
}
struct ConfigCellModel : Equatable, IdentifiableType {
static func == (lhs: ConfigCellModel, rhs: ConfigCellModel) -> Bool {
return lhs.model.item.symbol == rhs.model.item.symbol
}
var identity: String {
return model.item.symbol
}
let model: ConfigItemModel
}
J'ai essayé d'utiliser este mais je n'ai pas réussi à le faire fonctionner complètement, car je suppose que je n'ai pas fourni l'en-tête personnalisé de la bonne façon/moment.