具有自定义集合视图布局的Diffable Data Source



在这里,我创建了一个示例应用程序,该应用程序为具有自定义集合视图布局的集合视图使用不同的数据源。我使用的具体布局来自本教程。

如果您不想克隆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数据源通常与组合布局一起使用,尽管我在任何地方都没有看到这是一个要求。

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

问题是这一行:

func applySnapshot(animatingDifferences: Bool = true) {

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

嗨,现在回答已经太晚了,但我尝试了同样的方法和同样的问题

我的案例问题是集合中项目的数量查看

PinterestLayout中的82行"对于0中的项。<collectionView.numberOfItems(在节中:0({quot;

所以。。我将快照中的实际项目数从视图注入到自定义布局

myLayout.updateNumberOfItems(currentSnapshot.numberOfItems)
dataSource.apply(currentSnapshot)

只使用numberOfItems而不是collectionView.numberOfItems.

这对我来说是工作

如果我错了,请告诉我

最新更新