I am building an app where a user can read articles. Each article is written by an author, so, on the article view, when the user clicks on the author's profile picture it navigates to the Author's profile view.
In the Author Profile view, there is a "Follow" button, and in the same view, there are the statistics of the Author (ex. how many articles he/she wrote, how many followers they have, etc.). Something very close to this:
When the author profile view loads, everything is OK. But as soon as the user touches the "Follow" button, the app crashes with the following error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Section identifier count does not match data source count. This is most likely due to a hashing issue with the identifiers.'
These are the steps I follow:
Edit: Code part:
enum AuthorProfileSection {
case details
case stats
case articles
}
Datasource creation:
func configureDataSource() -> UICollectionViewDiffableDataSource<AuthorProfileSection, AnyHashable> {
let dataSource = UICollectionViewDiffableDataSource<AuthorProfileSection, AnyHashable>(collectionView: collectionView) { (collectionView, indexPath, object) -> UICollectionViewCell? in
if let object = object as? Author {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: AuthorDetailsCell.reuseIdentifier, for: indexPath) as! AuthorDetailsCell
cell.configure(with: object)
return cell
}
if let object = object as? AuthorStatsForAuthorProfile {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: AuthorStatCell.reuseIdentifier, for: indexPath) as! AuthorStatCell
cell.configure(with: object)
return cell
}
if let object = object as? Article {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: AuthorArticleCell.reuseIdentifier, for: indexPath) as! AuthorArticleCell
cell.configure(with: object)
return cell
}
return nil
}
return dataSource
}
Updating snapshot
fileprivate func updateSnapshot(animated: Bool = false) {
guard let authorUID = authorUID else { return }
Firebase.Database.database().fetchSelectedAuthorProfileData( authorUID: authorUID, fromArticleUID: self.articleUID) { authorProfileSection in
var snapshot = self.dataSource.snapshot()
// sections
snapshot.appendSections([.details, .stats, .articles])
snapshot.appendItems([authorProfileSection.details], toSection: .details)
snapshot.appendItems(authorProfileSection.stats ?? [], toSection: .stats)
snapshot.appendItems(authorProfileSection.articles ?? [], toSection: .articles)
self.dataSource.apply(snapshot, animatingDifferences: animated)
}
}
And the cell:
class AuthorStatCell: UICollectionViewCell, SelfConfiguringCell {
typealias someType = AuthorStatsForAuthorProfile
static var reuseIdentifier = "AuthorStatCell"
override init(frame: CGRect) {
super.init(frame: frame)
buildUI()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configure(with data: AuthorStatsForAuthorProfile) {
print(data)
}
fileprivate func buildUI() {
backgroundColor = UIColor(red: 0.20, green: 0.83, blue: 0.60, alpha: 1.00)
layer.cornerRadius = 15
}
}
And this is the result (in red the part that changes if I touch the "follow" button):
Here is where the app crashes. Any idea why?
I suspect, the issue is inside updateSnapshot() you are getting the current snapshot and adding 3 new sections to it every time you touch follow button
var snapshot = self.dataSource.snapshot()
// sections
snapshot.appendSections([.details, .stats, .articles])
try this
var snapshot = NSDiffableDataSourceSnapshot<AuthorProfileSection, AnyHashable>()
Or if you are calling another func like createSnapshot Before updateSnapshot then just try removing the line of appendSections
var snapshot = self.dataSource.snapshot()
// sections
// remove it
//snapshot.appendSections([.details, .stats, .articles])
snapshot.appendItems([authorProfileSection.details], toSection: .details)
snapshot.appendItems(authorProfileSection.stats ?? [], toSection: .stats)
snapshot.appendItems(authorProfileSection.articles ?? [], toSection: .articles)
self.dataSource.apply(snapshot, animatingDifferences: animated)
I’m not sure 100% 🤔 about it bcs I just on my phone rn