The definition of ITEM list below, could you see any problem here? @J0hn
class AlbumItem: Hashable {
let albumURL: URL
let albumTitle: String
let imageItems: [AlbumDetailItem]
init(albumURL: URL, imageItems: [AlbumDetailItem] = []) {
self.albumURL = albumURL
self.albumTitle = albumURL.lastPathComponent.displayNicely
self.imageItems = imageItems
}
func hash(into hasher: inout Hasher) {
hasher.combine(identifier)
}
static func == (lhs: AlbumItem, rhs: AlbumItem) -> Bool {
return lhs.identifier == rhs.identifier
}
private let identifier = UUID()
}
BTW, those unnecessary calling occurs in demo on session 10252,to reproduce this issue:
- add delegate for the collection view, disable prefetching to reduce logs:
private func configureHierarchy() {
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout())
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.backgroundColor = .systemBackground
// collectionView.prefetchDataSource = self
collectionView.isPrefetchingEnabled = false
collectionView.delegate = self
view.addSubview(collectionView)
}
2. implement the selection callback for removing item from snapshot:
extension PostGridViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("remove items at section:(\(indexPath.section)), item:(\(indexPath.item))")
var snapshot = dataSource.snapshot()
let identfiers = snapshot.itemIdentifiers(inSection: Section.ID.allCases[indexPath.section])
snapshot.deleteItems([identfiers[indexPath.item]])
dataSource.apply(snapshot, animatingDifferences: false)
}
}
- finally, remove reload stuff in cell registeration:
let cellRegistration = UICollectionView.CellRegistration<DestinationPostCell, DestinationPost.ID> { [weak self] cell, indexPath, postID in
guard let self = self else { return }
print("configure DestinationPostCell:(\(Unmanaged.passUnretained(cell).toOpaque())) at section:(\(indexPath.section)), item:(\(indexPath.item))")
let post = self.postsStore.fetchByID(postID)
let asset = self.assetsStore.fetchByID(post.assetID)
cell.configureFor(post, using: asset)
}
THEN I ran this demo and clicked the first item to remove it, similar log came out:
configure DestinationPostCell:(0x000000015ef11940) at section:(0), item:(0)
configure DestinationPostCell:(0x000000015ed20410) at section:(0), item:(1)
configure DestinationPostCell:(0x000000015ed21900) at section:(1), item:(0)
remove items at section:(0), item:(0)
configure DestinationPostCell:(0x000000015ed433c0) at section:(1), item:(2)
configure DestinationPostCell:(0x000000015ed433c0) at section:(0), item:(0)
configure DestinationPostCell:(0x000000015ed433c0) at section:(1), item:(0)
configure DestinationPostCell:(0x000000015ed433c0) at section:(1), item:(1)
configure DestinationPostCell:(0x000000015ef11940) at section:(1), item:(1)
-
—
J0hn
-
—
Frameworks Engineer
-
—
StanOZ
Add a CommentWhat do the equatable and hashable methods of your ITEM look like?
Please give it a try on iOS 15 beta 2, there are new optimizations in beta 2 (which were not in beta 1) that will reduce or eliminate the number of extra cells requested when you use
apply(_:animatingDifferences:). In some cases, you may still see a few extra cells requested, but this will usually only happen the first time you apply a snapshot. The reason that extra cells can be requested sometimes is because UICollectionView needs to perform self-sizing of some cells near the visible region in order to resolve estimated sizes and accurately determine which cells need to be visible, so in certain cases it will ask for cells that may not immediately become visible. However, in iOS 15 any extra cells requested for self-sizing will be kept cached by UICollectionView as prepared cells (similar to the way cells get prefetched), so that they can be immediately made visible when you scroll to them.Cool, I had retry it on iOS 15 beta2, it just works like a charm~