【问题标题】:Swift Diffable datasource will crash when Firebase .observe() updates valuesFirebase .observe() 更新值时,Swift Diffable 数据源将崩溃
【发布时间】:2021-11-06 17:36:21
【问题描述】:

我正在构建一个用户可以阅读文章的应用。每篇文章都由作者撰写,因此,在文章视图中,当用户点击作者的个人资料图片时,它会导航到作者的个人资料视图。

在作者简介视图中,有一个“关注”按钮,在同一视图中,有作者的统计信息(例如,他/她写了多少篇文章,他们有多少关注者等) .非常接近这个的东西:

当作者个人资料视图加载时,一切正常。但是一旦用户点击“关注”按钮,应用就会崩溃并出现以下错误:

由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“部分标识符计数与数据源计数不匹配。这很可能是由于标识符的散列问题。'

这些是我遵循的步骤:

  1. 作者个人资料视图中的用户
  2. 用户会看到“关注”按钮和显示有多少用户关注作者的统计数据
  3. 假设作者有 10 个关注者。用户触摸“关注”按钮
  4. 在幕后,我进入 Firebase,获取作者,然后使用 .observeSingleEvent() 和 setValue 将用户 ID 添加到字符串数组中:followers: ["asdm132123", "asdadsa12931", "!123123jsdfjsf"] ()
  5. 然后我使用 Firebase 的 .observe() 方法读取数据,将按钮状态从“关注”->“关注”更新,并将关注者的值从“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
    }
}

这就是结果(如果我点击“关注”按钮,红色部分会发生变化):

这是应用程序崩溃的地方。知道为什么吗?

【问题讨论】:

  • 您需要展示创建快照的代码以及如何为您的部分项目生成标识符。
  • @Paulw11 给你

标签: ios swift firebase-realtime-database uicollectionviewdiffabledatasource


【解决方案1】:

我怀疑,问题出在 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% ? 关于它,因为我只是在手机上 rn

【讨论】:

  • 感谢您的意见!使用 var snapshot = NSDiffableDataSourceSnapshot() 后,它开始使用 2 个警告:1)如果我再次尝试按下“关注”按钮,它会因错误“致命:提供的项目标识符不唯一”而崩溃—— > 我通过为每个涉及的模型提供一个唯一的 ID 来解决这个问题。 2)现在,每次我按下“关注”按钮时,它都会重新加载所有数据,看起来它会堆叠 Stats 部分,然后恢复正常。我按下按钮的次数越多,重新加载数据所需的时间就越长。很奇怪。
  • 所以结果是在调用 Firebase .observe() 方法之前初始化我的数据数组,导致数组一遍又一遍地附加相同的数据(我相信因为我没有删除观察) .因此,每次我按下“关注”按钮时,都会有一堆部分。
猜你喜欢
  • 2020-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多