Greetings I have the disadvantage that the cells of the tableview are duplicated in a random way, at certain times the event occurs, not always
i think i need to clean or reload data but im not sure, could you help please.
final class MovementsDatasource: NSObject, PaginatedDatasource {
typealias Values = MovementsSectionModel
private let repository: TransactionsRepositoryProtocol
private let disposeBag = DisposeBag()
private let fetching = ActivityIndicator()
private let id: String, cvl: String
private let rowsObserver = PublishSubject<[Values]>()
var values = [Values]() { didSet { self.rowsObserver.onNext(self.values) } }
var page = 0
var hasNextPage = false
init(repository: TransactionsRepositoryProtocol, id: String, cvl: String) {
self.id = id
self.cvl = cvl
self.repository = repository
}
func getActivityIndicator() -> ActivityIndicator { self.fetching }
func getValuesObserver() -> Observable<[Values]> { self.rowsObserver }
func getNextPage() {
guard self.hasNextPage else { return }
getMovements(for: self.id, cvl: self.cvl, page: self.page)
}
func getFirstPage() {
self.page = 0
self.hasNextPage = false
self.values = []
getMovements(for: self.id, cvl: self.cvl, page: self.page)
}
}
extension MovementsDatasource {
private func getMovements(for productID: String, cvl: String, page: Int) {
self.repository
.movements(userCVL: cvl, ibanAccountId: productID, page: page)
.trackActivity(self.fetching)
.subscribe(onNext: { [weak self] response in
guard let _self = self else { return }
_self.hasNextPage = response.hasNextPage
_self.page = _self.hasNextPage ? (_self.page + 1) : _self.page
_self.publish(response)
})
.disposed(by: self.disposeBag)
}
private func publish(_ response: MovementsResponse) {
guard let rawMovement = response.values else { return }
let newRows = self.transform(rawMovement)
var rows = self.values
if !rows.isEmpty { rows += newRows }
else { rows = newRows }
self.values = self.merge(rows)
}
internal func transform(_ movements: [Movement]) -> [MovementsSectionModel] {
movements
.map { $0.movementDate.displayTimestamp() }
.unique()
.map { title -> MovementsSectionModel in
let sorted = movements.filter { $0.movementDate.displayTimestamp() == title }
return MovementsSectionModel(header: title, items: sorted)
}
}
internal func merge(_ sections: [MovementsSectionModel]) -> [MovementsSectionModel] {
sections
.map { $0.header }
.unique()
.map { title -> MovementsSectionModel in
let merged = sections.reduce(into: [MovementCellViewModel]()) {
accumulator, section in
if section.header == title { accumulator += section.items }
}
return MovementsSectionModel(header: title, items: merged)
}
}
}
extension MovementsDatasource {
func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
self.values[section].items.count
}
func numberOfSections(in _: UITableView) -> Int { self.values.count }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard !self.values.isEmpty, let cell = tableView.dequeueReusableCell(withIdentifier: MovementCell.reuseID, for: indexPath) as? MovementCell
else {
return UITableViewCell(frame: .zero)
}
let section = indexPath.section
let index = indexPath.item
if !self.values.isEmpty {
cell.viewModel = self.values[section].items[index]
}
return cell
}
}