Swift 当 Firebase .observe() 更新值时,Diffable 数据源会崩溃
Swift Diffable datasource will crash when Firebase .observe() updates values
我正在构建一个用户可以阅读文章的应用程序。每篇文章都是由一位作者撰写的,因此,在文章视图中,当用户单击作者的个人资料图片时,它会导航到作者的个人资料视图。
在作者个人资料视图中,有一个“关注”按钮,在同一视图中,有作者的统计信息(例如 he/she 发表了多少篇文章,他们有多少关注者, ETC。)。非常接近于此的东西:
加载作者个人资料视图时,一切正常。但是一旦用户触摸“关注”按钮,应用程序就会崩溃并出现以下错误:
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.'
这些是我遵循的步骤:
- 作者个人资料视图中的用户
- 用户看到“关注”按钮和显示有多少用户关注作者的统计数据
- 假设作者有 10 个关注者。用户点击“关注”按钮
- 在幕后,我进入 Firebase,获取作者,并将用户 ID 添加到字符串数组中:followers: ["asdm132123", "asdadsa12931", "!123123jsdfjsf"] 通过使用 .observeSingleEvent()和 setValue()
- 然后我使用 Firebase 的 .observe() 方法读取数据,从“Follow”-->“Following”更新按钮状态并增加 followers'来自“10”的值 --> “11”
编辑:代码部分:
enum AuthorProfileSection {
case details
case stats
case articles
}
数据源创建:
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
}
正在更新快照
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)
}
}
单元格:
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
}
}
这是结果(红色部分是我点击“关注”按钮后发生变化的部分):
这是应用程序崩溃的地方。知道为什么吗?
我怀疑,问题出在 updateSnapshot() 内部,您每次触摸关注按钮时都会获取当前快照并向其中添加 3 个新部分
var snapshot = self.dataSource.snapshot()
// sections
snapshot.appendSections([.details, .stats, .articles])
试试这个
var snapshot = NSDiffableDataSourceSnapshot<AuthorProfileSection, AnyHashable>()
或者,如果您在 updateSnapshot 之前调用另一个函数,例如 createSnapshot,那么只需尝试删除 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)
我不是 100% 确定,因为我刚刚在我的 phone rn
我正在构建一个用户可以阅读文章的应用程序。每篇文章都是由一位作者撰写的,因此,在文章视图中,当用户单击作者的个人资料图片时,它会导航到作者的个人资料视图。
在作者个人资料视图中,有一个“关注”按钮,在同一视图中,有作者的统计信息(例如 he/she 发表了多少篇文章,他们有多少关注者, ETC。)。非常接近于此的东西:
加载作者个人资料视图时,一切正常。但是一旦用户触摸“关注”按钮,应用程序就会崩溃并出现以下错误:
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.'
这些是我遵循的步骤:
- 作者个人资料视图中的用户
- 用户看到“关注”按钮和显示有多少用户关注作者的统计数据
- 假设作者有 10 个关注者。用户点击“关注”按钮
- 在幕后,我进入 Firebase,获取作者,并将用户 ID 添加到字符串数组中:followers: ["asdm132123", "asdadsa12931", "!123123jsdfjsf"] 通过使用 .observeSingleEvent()和 setValue()
- 然后我使用 Firebase 的 .observe() 方法读取数据,从“Follow”-->“Following”更新按钮状态并增加 followers'来自“10”的值 --> “11”
编辑:代码部分:
enum AuthorProfileSection {
case details
case stats
case articles
}
数据源创建:
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
}
正在更新快照
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)
}
}
单元格:
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
}
}
这是结果(红色部分是我点击“关注”按钮后发生变化的部分):
这是应用程序崩溃的地方。知道为什么吗?
我怀疑,问题出在 updateSnapshot() 内部,您每次触摸关注按钮时都会获取当前快照并向其中添加 3 个新部分
var snapshot = self.dataSource.snapshot()
// sections
snapshot.appendSections([.details, .stats, .articles])
试试这个
var snapshot = NSDiffableDataSourceSnapshot<AuthorProfileSection, AnyHashable>()
或者,如果您在 updateSnapshot 之前调用另一个函数,例如 createSnapshot,那么只需尝试删除 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)
我不是 100% 确定,因为我刚刚在我的 phone rn