3 votes

UITableView effectuant la suppression et l'insertion de lignes de manière animée en cascade

Je suis intéressé par la suppression d'un lot de lignes à partir d'une base de données. UITableView en utilisant l'animation tableView.deleteRows(at: [singleIndexPath], with: .automatic) . Cependant, mon objectif est de cascader l'animation de suppression afin qu'elle se produise dans une animé en cascade de sorte qu'au lieu de retirer le lot entier de lignes, l'animation les montre retirées l'une après l'autre.

J'ai découvert une aide UITableView où j'obtiens un bloc d'achèvement après qu'une animation est terminée, comme tel :

extension UITableView {

    /// Perform a series of method calls that insert, delete, or select rows and sections of the table view.
    /// This is equivalent to a beginUpdates() / endUpdates() sequence,
    /// with a completion closure when the animation is finished.
    /// Parameter update: the update operation to perform on the tableView.
    /// Parameter completion: the completion closure to be executed when the animation is completed.

    func performUpdate(_ update: ()->Void, completion: (()->Void)?) {

        CATransaction.begin()
        CATransaction.setCompletionBlock(completion)

        // Table View update on row / section
        beginUpdates()
        update()
        endUpdates()

        CATransaction.commit()
    }

}

Mon problème est de trouver comment utiliser le bloc automatiser l'animation de la suppression de ligne (et plus tard, de l'insertion de ligne). Actuellement, l'exemple de code suivant avec deux rangées IndexPath a toujours une animation qui se produit en même temps, ce qui n'est pas mon objectif.

    let singleIndexPath = IndexPath(row: 0, section: 0)
    let anotherIndexPath = IndexPath(row: 1, section: 0)

    self.tableView.performUpdate({

        self.tableView.deleteRows(at: [singleIndexPath, anotherIndexPath], with: .automatic)
        self.tableView.insertRows(at: [singleIndexPath, anotherIndexPath], with: .left)
        //Happening at the same time, which is not what I want
    }, completion: {

    })

Tout conseil est le bienvenu.

1voto

paulvs Points 386

Suppression des lignes de la vue en cascade des tableaux

Utilisation :

let indexPathsToDelete = [IndexPath(row: 1, section: 0), IndexPath(row: 4, section: 0), IndexPath(row: 6, section: 0)]
 deleteRowsAt(indexPaths: indexPathsToDelete, in: tableView)

Code :

func deleteRowsAt(indexPaths: [IndexPath], in tableView: UITableView) {
    var state = (0 ..< tableView.numberOfSections).map {
        Array(0 ..< tableView.numberOfRows(inSection: $0))
    }

    func cascadeDeleteAt(indexPath indexPathToDelete: IndexPath) {

        // Get the current row for the index path we wish to delete.
        // It could be diffrent to its original index path if other rows have been deleted.
        guard let currentRow = state[indexPathToDelete.section].index(of: indexPathToDelete.row) else { return }

        let currentIndexPath = IndexPath(row: currentRow, section: indexPathToDelete.section)
        print(currentIndexPath)

        // --- IMPLEMENT THE DELETION FROM YOUR DATA SOURCE ---
        source.remove(at: currentIndexPath.row)

        state[indexPathToDelete.section].remove(at: currentIndexPath.row)

        tableView.performUpdate({
            tableView.deleteRows(at: [currentIndexPath], with: .left)
        }, completion: {
            guard var idx = indexPaths.index(of: indexPathToDelete) else { return }
            idx += 1
            if idx < indexPaths.count {
                let nextIndexPathToDelete = indexPaths[idx]
                cascadeDeleteAt(indexPath: nextIndexPathToDelete)
            }
        })
    }

    if let indexPath = indexPaths.first {
        cascadeDeleteAt(indexPath: indexPath)
    }
}

Lorsque l'on supprime des lignes en cascade (c'est-à-dire en supprimant une ligne à la fois au lieu de toutes les lignes en même temps), les parties délicates sont les suivantes :

  1. Après la suppression d'une ligne, d'autres index (chemins d'index et aussi index dans les sources de données) ne pointent plus là où ils étaient.
  2. La fonction performUpdate doit être appelé à l'intérieur d'une fonction récursive pour que la ligne suivante ne soit supprimée qu'après la suppression de la ligne actuelle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X