I'm working on the collection view list cell and I was wondering how to update the indexPath when I use the diffable data source and snapshot on iOS14.
In my ViewController's viewdidload, I called configureDataSource method which registers cell information. Also, I have a displayEvents method that fetches Events data from the backend and displays them on the collection view cell. The eventDataSource holds an array of Events, so when the Event data are fetched, it updates the array so the ViewController can display data.
I also have an addEvent function which is called from EventActionModalViewController, like a user types the event name and sends .save API request to store the data in the database. It works fine, I mean successfully add data backend and display the new event on the collection view list. However, the problem is the collection view's indexPath is not updated.
For instance, if there are already two events in the collection view, their indexPath are [0,0] and [0,1]
. (I printed them out in print("here is the indexPath: \(indexPath)")
)
And after I add the new event, there are three events on the collection view, which is correct, but the indexPath becomes [0,0],[0,0] and [0,1]
. So I think the indexPath of already displayed events are not updated. Is applying a snapshot not enough to update the indexPath of each cell? I was thinking even after applying snapshot, it still needs to reload the collection view to apply a new indexPath to the cell, or something similar.
Has anyone faced the same issue? If so, how did you apply the new indexPath to the cell? I also have a function to delete the cell, but it doesn't update the indexPath as well. Btw, I'm working on the app for iOS14, so cannot use one for iOS15...
private var eventDataSource = EventDataSource()
override func viewDidLoad() {
super.viewDidLoad()
setupCollectionView() // -> create collection view and set constraints
configureDataSource()
displayEvents()
}
func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<ListCell, Event> { cell, indexPath, Event in
cell.Event = Event
let moreAction = UIAction(image: Images.setting) { _ in
let vc = EventActionModalViewController();
vc.modalPresentationStyle = .overCurrentContext
print("here is the indexPath: \(indexPath)")
vc.indexPath = indexPath
self.tabBarController?.present(vc, animated: false, completion: nil)
}
let moreActionButton = UIButton(primaryAction: moreAction)
moreActionButton.tintColor = UIColor.ouchienLightGray()
let moreActionAccessory = UICellAccessory.CustomViewConfiguration(
customView: moreActionButton,
placement: .trailing(displayed: .whenEditing, at: { _ in return 0 })
)
cell.accessories = [
.customView(configuration: moreActionAccessory),
.disclosureIndicator(displayed: .whenNotEditing, options: .init(tintColor: .systemGray))
]
}
dataSource = UICollectionViewDiffableDataSource<Section, Event>(collectionView: collectionView) {
(collectionView, indexPath, Event) -> UICollectionViewCell? in
let cell = collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: Event)
return cell
}
}
func displayEvents() {
eventDataSource.fetchEvents { [weak self] in
self?.applySnapshot(animatingDifferences: true)
}
}
func addEvent(EventTitle: String) {
eventDataSource.save(eventTitle: EventTitle, completion: { [weak self] in
self?.applySnapshot(animatingDifferences: true)
})
}
func applySnapshot(animatingDifferences: Bool = true) {
snapshot = NSDiffableDataSourceSnapshot<Section, Event>()
snapshot.appendSections([.List])
snapshot.appendItems(eventDataSource.Events)
dataSource?.apply(snapshot, animatingDifferences: animatingDifferences)
}
CodePudding user response:
The index path you pass in moreAction
is the one captured at cell registration, which happens only if cell is created, but not recycled.
You need to call UICollectionView.indexPathForCell
to get the right index at any time.