【问题标题】:Diffable Data Source with a custom collection view layout?具有自定义集合视图布局的 Diffable 数据源?
【发布时间】:2021-02-15 14:41:54
【问题描述】:

Here 我创建了一个示例应用程序,该应用程序将可区分数据源用于具有自定义集合视图布局的集合视图。我使用的具体布局来自this教程。

如果您不想克隆 repo 并自己尝试,这里是代码的相关部分。

import UIKit
let cellIdentifier = "testRecordCell"

struct Record:Hashable {
    let identifier = UUID()
    func hash(into hasher: inout Hasher) {
        hasher.combine(identifier)
    }
    static func == (lhs: Record, rhs: Record) -> Bool {
        return lhs.identifier == rhs.identifier
    }
    var timeStamp: Date
    init(daysBack: Int){
        self.timeStamp = Calendar.current.date(byAdding: .day, value: -1*daysBack, to: Date())!
    }
}
class Cell:UICollectionViewCell {
}

class Section: Hashable {
  var id = UUID()
  // 2
  var records:[Record]
  
  init(records:[Record]) {
    self.records = records
  }
  
  func hash(into hasher: inout Hasher) {
    hasher.combine(id)
  }
  
  static func == (lhs: Section, rhs: Section) -> Bool {
    lhs.id == rhs.id
  }
}

extension Section {
  static var allSections: [Section] = [
    Section(records: [
      Record(daysBack: 5),Record(daysBack: 6)
    ]),
    Section(records: [
      Record(daysBack: 3)
    ])
    ]
}

class ViewController: UICollectionViewController {

    private lazy var dataSource = makeDataSource()
    private var sections = Section.allSections

    fileprivate typealias DataSource = UICollectionViewDiffableDataSource<Section,Record>
    fileprivate typealias DataSourceSnapshot = NSDiffableDataSourceSnapshot<Section,Record>
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.collectionView?.register(Cell.self, forCellWithReuseIdentifier: cellIdentifier)
        applySnapshot()
        if let layout = collectionView.collectionViewLayout as? PinterestLayout {
            layout.delegate = self
        }
    }
}
extension ViewController {
    
    fileprivate func makeDataSource() -> DataSource {
        let dataSource = DataSource(
            collectionView: self.collectionView,
            cellProvider: { (collectionView, indexPath, testRecord) ->
              UICollectionViewCell? in
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath)
                cell.backgroundColor = .black
                return cell
            })
        return dataSource
    }
    func applySnapshot(animatingDifferences: Bool = true) {
        // 2
        var snapshot = DataSourceSnapshot()
        snapshot.appendSections(sections)
        sections.forEach { section in
          snapshot.appendItems(section.records, toSection: section)
        }
        //This part errors out: "request for number of items in section 0 when there are only 0 sections in the collection view"
        dataSource.apply(snapshot, animatingDifferences: animatingDifferences)
    }
}
extension ViewController: PinterestLayoutDelegate {
    func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath: IndexPath) -> CGFloat {
        return CGFloat(10)
    }
}

不知何故,布局没有注册集合视图中确实包含项目和部分。正常运行时,在尝试应用快照时报错:“当集合视图中只有 0 个部分时,请求第 0 部分中的项目数”

然后,在 Pinterest 布局的 prepare() 函数中,当我设置断点并检查 collectionView.numberOfSections() 时,它返回 0。所以不知何故,快照没有与集合视图通信。请注意,我从不使用 collectionView 的委托方法 numberOfSections,因为我使用的是 diffable 数据源...

我的印象是 diffable 数据源通常与组合布局一起使用,尽管我在任何地方都没有看到这是必需的。

那么有什么办法可以做到吗?

【问题讨论】:

  • @matt 我从本教程复制了快照附加部分代码:raywenderlich.com/…。我不确定它是如何不正确的。
  • 是的,不是这样。请参阅下面的答案。
  • 在我看来你在stackoverflow.com/questions/64509408/…问了同样的问题
  • @matt 我基本上做到了。我问了一个关于我遇到的特定错误的问题,然后问了一个关于一般问题的问题。我认为这个问题更好,因为它涉及一个最小的可重现示例,并且对错误发生的原因有一个实际的答案。但是,我宁愿不删除那个,以奖励回答者为寻找答案而遇到的麻烦。我猜这两个问题都打开不太好,但我不知道还能做什么。

标签: ios swift uicollectionview uicollectionviewlayout uicollectionviewdiffabledatasource


【解决方案1】:

问题出在这一行:

func applySnapshot(animatingDifferences: Bool = true) {

true 更改为false,您就不会再崩溃了。

【讨论】:

  • 谢谢!也许 animatingDifferences 仅适用于组合布局?
  • 如果您明白我的意思,您的自定义布局肯定有问题,它以错误的顺序提问。您可以通过实验替换不同的布局来轻松测试该假设。 (我注意到即使在我们停止崩溃后,集合视图本身看起来也很糟糕,这表明布局存在有缺陷。)
  • 一个流式布局好像没有这个问题。我选择了 Pinterest 布局,因为我认为它在教程中必须是“正确”布局的示例。但是,它可能没有实现流布局或组合布局确实实现的动画所需的某些方法。我想知道这些布局是否有在线某个地方的源代码?
  • “一个流式布局好像没有这个问题。”是的,我也注意到了。所以我认为布局有缺陷。
  • 谢谢,它有效。我有同样的错误。而且我也无法弄清楚自定义布局可能在哪里出现问题。以及为什么我需要关闭动画。解决这样的问题看起来像是 hack。我在做一些概念上的错误。
猜你喜欢
  • 1970-01-01
  • 2017-05-22
  • 1970-01-01
  • 2015-06-12
  • 1970-01-01
  • 1970-01-01
  • 2016-07-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多