Martin
Martin

Reputation: 12215

UITableViewDiffableDataSource set different cell animations

I'm using UITableViewDiffableDataSource to render cells, and I wonder how to animate rows granularily.

There's a property

self.dataSource?.defaultRowAnimation = .fade

which apply for all rows of the tableView, but I would like some animation for certain cells, and NO animation for others. The "default" in "defaultRowAnimation" suggest there are other methods.

Unfortunately, Apple documentation on the subjet is a bit light

Is there a method that asks a RowAnimation according to the given IndexPath for example?

Upvotes: 24

Views: 4295

Answers (2)

Rob
Rob

Reputation: 438112

One simple approach is to call apply once for the changes not to be animated and again, separately, for the changes to be animated. Once you are doing that, you can either:

  1. When calling apply(_:animatingDifferences:), pass an animatingDifferences of false. Even if a defaultRowAnimation has been set for a particular animation, passing an animatingDifferences of false will prevent any animation from taking place for that particular apply call.

  2. Alternatively, in a permutation of John Scalo’s suggestion (+1), before calling apply for the rows you do not want animated, change the data source’s defaultRowAnimation to .none. Just remember to change it back so future apply calls will be animated correctly. As the docs for defaultRowAnimation say:

    If you set the value of this property, the new value becomes the default row animation for the next update that uses apply(_:animatingDifferences:completion:).

Upvotes: 1

John Scalo
John Scalo

Reputation: 3411

Unfortunately there isn't a delegate method or similar that asks you which animation to use for which cell, however in UITableViewDiffableDataSource.update(sections:) you can choose which animation to use based on any criteria you like as long as its represented in the model. E.g.


class MyTableViewDataSource: UITableViewDiffableDataSource<ListSectionID, ListItemID> {

func update(animated: Bool = true) {
    var newSnapshot = NSDiffableDataSourceSnapshot<ListSectionID, ListItemID>()
    newSnapshot.appendSections([.theSection])

    if let items = DataManager.shared.itemsUsingFadeAnimation {
        let ids = items.map { ListItemID(id: $0.id) }
        newSnapshot.appendItems(items, toSection: .theSection)
        .defaultRowAnimation = .fade
        apply(newSnapshot, animatingDifferences: animated)
    }
    if let items = DataManager.shared.itemsUsingMiddleAnimation {
        let ids = items.map { ListItemID(id: $0.id) }
        // insert these ids into the snapshot using `appendItems` or `insertItems`
        .defaultRowAnimation = .middle
        apply(newSnapshot, animatingDifferences: animated)
    }

}

Upvotes: 3

Related Questions