Problem
When I reconfigure a collection view snapshot and apply it to my complex production collection view with list layout, the UI updates slowly, unless I don't animate the differences, even though I'm only reconfiguring the specific item identifiers of the cells that should be updated.
I thought that maybe I could speed up the animations of the UI updates by applying the snapshot to a specific section (dataSource?.apply(sectionSnapshot, to: .main)
) instead of to the whole collection view (dataSource?.apply(wholeSnapshot)
).
The problem is that I can't reconfigure the item identifiers of a single section snapshot to then apply the updated snapshot.
Question
Given the following sample app, can anybody edit reconfigureMainSection()
so that, when invoked, the .main
section cell registrations are called, consequently invoking print("Reconfiguring")
?
Sample app
This collection view with list layout and diffable data source has 1 section and 2 rows.
You can tap the right bar button item to call reconfigureMainSection()
.
class ViewController: UICollectionViewController {
var snapshot: NSDiffableDataSourceSnapshot<Section, String> {
var snapshot = NSDiffableDataSourceSnapshot<Section, String>()
snapshot.appendSections([.main])
snapshot.appendItems(["one", "two"], toSection: .main)
return snapshot
}
var dataSource: UICollectionViewDiffableDataSource<Section, String>?
enum Section {
case main
}
init() {
super.init(collectionViewLayout: .init())
collectionView.collectionViewLayout = createLayout()
configureDataSource()
}
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = .init(
title: "Reconfigure",
style: .plain,
target: self,
action: #selector(reconfigureMainSection)
)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, String> { cell, indexPath, itemIdentifier in
print("Reconfiguring")
}
dataSource = .init(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in
collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier)
}
dataSource?.apply(self.snapshot, animatingDifferences: false)
}
func createLayout() -> UICollectionViewLayout {
return UICollectionViewCompositionalLayout { section, layoutEnvironment in
let config = UICollectionLayoutListConfiguration(appearance: .plain)
return NSCollectionLayoutSection.list(using: config, layoutEnvironment: layoutEnvironment)
}
}
@objc func reconfigureMainSection() {
var sectionSnapshot = NSDiffableDataSourceSectionSnapshot<String>()
sectionSnapshot.append(snapshot.itemIdentifiers(inSection: .main))
// reconfigure the section snapshot
dataSource?.apply(sectionSnapshot, to: .main)
}
}
Environment
MacBook Air M1 8GB
macOS Sonoma 14.5
Xcode 15.4
iPhone 15 Pro simulator on iOS 17.5
@Filippo02 Currently, there is no a 1-1 mapping for that method for sections. To get equivalent behavior in sections, you may need to manually get the indexPath and reconfigureItemsAtIndexPaths