Hi,
Note: Am required to support iOS 14, and so am unable to use some of the new APIs available in iOS 15 related to this question. I have also created a similar setup with a UITableView, however, am opting for the UICollectionView with list content as the collapsable sections are far nicer to work with.
Anyway, I have a simple UICollectionView setup using the UICollectionViewCompositionalLayout and UICollectionViewListCell to render a simple settings view.
Some of these views have accessories such as UISwitch elements and some display things like a .checkmark. They all render fine and ultimately they update to the expected state after applying the section snapshot. I expect this as the Identifiable ID has not changed, but the equatable check has. However, when the associated data item is updated it animates the change with a slight fade.
When I subclassed the UICollectionViewCompositionalLayout to take a closer look I noticed that the change is being made by deleting and inserting an item in the same location, rather than the expected reload action type.
I have also tried setting up so that the diffable data source only uses identifiers (where the cell registrations grab the relative item), but again when I reload the sections I get the slight fade.
Currently am using the following:
func setDisplaySections(_ sections: [Settings.Display.Section]) {
let isInitialData = dataSource.snapshot().sectionIdentifiers.isEmpty
var snapshot = NSDiffableDataSourceSnapshot<Settings.Display.Section.ID, ListItem>()
let sectionIds = sections.map(\.id)
snapshot.appendSections(sectionIds)
sections.forEach { section in
var sectionSnapshot = NSDiffableDataSourceSectionSnapshot<ListItem>()
// Append the section item as the layout is using the first item as the header.
let headerItem = ListItem.header(id: section.id, title: section.title, isCollapsable: section.isCollapsable)
sectionSnapshot.append([headerItem])
// Append items to the section
let items = section.items.map(transformToListItem)
sectionSnapshot.append(items, to: headerItem)
// Adjust expanded state
let isExpanded = isSectionExpanded(section.id)
if isInitialData, section.isCollapsable, !isExpanded {
sectionSnapshot.collapse([headerItem])
} else {
sectionSnapshot.expand([headerItem])
}
dataSource.apply(sectionSnapshot, to: section.id, animatingDifferences: !isInitialData)
}
}
Question: I am wondering if there is a way to tell the collection view to just reload/update the cell without the insert/delete to avoid this slight fade when these values change. Or should I take another look at subclassing UICollectionViewCompositionalLayout to convert the insert/delete pairs for this scenario into the update type?
Also, am aware the UITableViewDiffableDataSource will let you assign the defaultRowAnimation - but it does not seem to let you assign per update type (insert/delete/reload etc). And assigning none will also cancel some of the accessory animations, assigning fade will produce the same issue as above.
Some screen grabs (unable to upload movie):
Before switch is toggled:
During animation of toggle: