How to model updated items with UICollectionViewDiffableDataSource

555 views Asked by At

I'm struggling to understand how to use UICollectionViewDiffableDataSource and NSDiffableDataSourceSnapshot to model change of items.

Let's say I have a simple item which looks like this:

struct Item {
    var id: Int
    var name: String
}

Based on the names of the generic parameters, UICollectionViewDiffableDataSource and NSDiffableDataSourceSnapshot should operate not with Item itself, but only with identifier, which Int in this example.

On the other hand, again based on names of generic parameters, UICollectionView.CellRegistration should operate on complete Item's. So my guess is that UICollectionViewDiffableDataSource.CellProvider is responsible for finding complete Item's by id. Which is unfortunate, because then aside from snapshots, I need to maintain a separate storage of items. And there is a risk that this storage may go out of sync with snapshots.

But it is still not clear to me how do I inform UICollectionViewDiffableDataSource that some item changed its name without changing its id. I want UICollectionView to update the relevant cell and animate change in content size, but I don't want insertion or removal animation.

1

There are 1 answers

0
Carter Foughty On

There are two approaches that would work solve your problem in this scenario.

  1. The first is to conform your Item model to the hashable protocol. This would allow you to use the entire model as an identifier, and the cell provider closure would pass you an object of type Item. UICollectionViewDiffableDataSource would use the hash value for each instance of your model (which would consider both the id and name properties, thereby solving your name changing issue) to identify the data for a cell. This is better than trying to trick the collection view data source into considering only the id as the identifier because, as you stated, other aspects of the model might change. The whole point of structs is to act as a value-type, where the composition of all the model's properties determine its 'value'...no need to trick the collection view data source into looking only at Item.id.

  2. Do as you said, and create a separate dictionary in which you can retrieve the Items based on their id's. While it is slightly more work to maintain a dictionary, it is a fairly trivial difference in terms of lines of code. All you should do is dump and recalculate the dictionary every time you apply a new snapshot. In this case, to update a cell when the model changes, make sure to swap out the model in your dictionary and call reloadItem on your snapshot.

While the second option is generally my preferred choice because the point of diffable data source is to allow for the handling of massive data sets by only concerning the data source with a simple identifier for each item, in this case your model is so simple that there's really no concern about wasted compute time calculating hash values, etc. If you think your model is likely to grow over time, I would probably go with the dictionary approach.