【发布时间】: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