具有自定义集合视图布局的可区分数据源?
Diffable Data Source with a custom collection view layout?
Here I have created a sample app that uses diffable data source for a collection view with a custom collection view layout. The specific layout I am using is from this教程。
如果您不想克隆存储库并自己尝试,这里是代码的相关部分。
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() 它 returns 0 时。所以不知何故快照没有与集合通信看法。请注意,我从不使用 collectionView 的委托方法 numberOfSections,因为我使用的是 diffable 数据源...
我的印象是 diffable 数据源通常与组合布局一起使用,尽管我在任何地方都没有看到这是一个要求。
那么有什么办法可以做到这一点吗?
问题出在这一行:
func applySnapshot(animatingDifferences: Bool = true) {
将true
更改为false
,您就不会再崩溃了。
嗨,现在回答已经太晚了,但我尝试了同样的方法和同样的问题
我的案例问题是在 collectionView 中处理 numberOfItems
下方 PinterestLayout 中的 82 行
“对于项目 0..
所以..我将快照中的实际 numberOfItems 从视图注入到自定义布局
myLayout.updateNumberOfItems(currentSnapshot.numberOfItems)
dataSource.apply(currentSnapshot)
并且只使用 numberOfItems 而不是 collectionView.numberOfItems。
对我有用
如果我错了请告诉我,谢谢")
Here I have created a sample app that uses diffable data source for a collection view with a custom collection view layout. The specific layout I am using is from this教程。
如果您不想克隆存储库并自己尝试,这里是代码的相关部分。
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() 它 returns 0 时。所以不知何故快照没有与集合通信看法。请注意,我从不使用 collectionView 的委托方法 numberOfSections,因为我使用的是 diffable 数据源...
我的印象是 diffable 数据源通常与组合布局一起使用,尽管我在任何地方都没有看到这是一个要求。
那么有什么办法可以做到这一点吗?
问题出在这一行:
func applySnapshot(animatingDifferences: Bool = true) {
将true
更改为false
,您就不会再崩溃了。
嗨,现在回答已经太晚了,但我尝试了同样的方法和同样的问题
我的案例问题是在 collectionView 中处理 numberOfItems
下方 PinterestLayout 中的 82 行
“对于项目 0.. 所以..我将快照中的实际 numberOfItems 从视图注入到自定义布局 并且只使用 numberOfItems 而不是 collectionView.numberOfItems。 对我有用 如果我错了请告诉我,谢谢")myLayout.updateNumberOfItems(currentSnapshot.numberOfItems)
dataSource.apply(currentSnapshot)