0

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
    }
}
mag_zbc
  • 6,801
  • 14
  • 40
  • 62
Zac Mazk
  • 1
  • 3
  • Your `tableView(:cellForRowAt:)` method simply installs a viewModel object into a cell of type `MovementCell`. You don't show the code that configures your cell. If you want help figuring out a problem with the way your cells are configured to display, you need to show the code that does that. (Do you have a didSet on your `MovementCell.viewModel`?) – Duncan C Oct 21 '21 at 19:41
  • Where do you call `tableView.reloadData()`? – Daniel T. Oct 21 '21 at 22:55
  • What does `displayTimestamp()` return? What is the type of `items` in `MovementsSectionModel`? – Daniel T. Oct 22 '21 at 11:52

0 Answers0