UICollectionViewDiffableDataSource: запрос количества элементов в разделе 0, когда в представлении коллекции только 0 разделов
Я пытаюсь создать график, в котором каждый раздел представляет собой день, а каждый день имеет много элементов (записей). Вот мой раздел (дневной) класс:
class YearMonthDay: Comparable, Hashable {
let year: Int
let month: Int
let day: Int
init(year: Int, month: Int, day: Int) {
self.year = year
self.month = month
self.day = day
}
init(date: Date) {
let comps = Calendar.current.dateComponents([.year, .month, .day], from: date)
self.year = comps.year!
self.month = comps.month!
self.day = comps.day!
}
func hash(into hasher: inout Hasher) {
hasher.combine(year)
hasher.combine(month)
hasher.combine(day)
}
var date: Date {
var dateComponents = DateComponents()
dateComponents.year = year
dateComponents.month = month
dateComponents.day = day
return Calendar.current.date(from: dateComponents)!
}
static func == (lhs: YearMonthDay, rhs: YearMonthDay) -> Bool {
return lhs.year == rhs.year && lhs.month == rhs.month && lhs.day == rhs.day
}
static func < (lhs: YearMonthDay, rhs: YearMonthDay) -> Bool {
if lhs.year != rhs.year {
return lhs.year < rhs.year
} else {
if lhs.month != rhs.month {
return lhs.month < rhs.month
} else {
return lhs.day < rhs.day
}
}
}
}
Как вы можете видеть, я добавляю атрибуты года, месяца и дня в свои разделы и использую их, чтобы сделать каждый из них "моющимся", так что, надеюсь, на каждый день будет максимум 1 раздел.
Вот моя коллекция ViewController...
class TimelineViewController: UICollectionViewController {
private lazy var dataSource = makeDataSource()
fileprivate typealias DataSource = UICollectionViewDiffableDataSource<YearMonthDay,TestRecord>
fileprivate typealias DataSourceSnapshot = NSDiffableDataSourceSnapshot<YearMonthDay,TestRecord>
public var data: [YearMonthDay:[TestRecord]] = [:]
var delegate: TimelineViewControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
guard let data = delegate?.dataForTimelineView() else { return }
self.data = data
collectionView.showsHorizontalScrollIndicator = true
configureHierarchy()
configureDataSource()
applySnapshot()
}
}
extension TimelineViewController {
fileprivate func makeDataSource() -> DataSource {
let dataSource = DataSource(
collectionView: collectionView,
cellProvider: { (collectionView, indexPath, testRecord) ->
UICollectionViewCell? in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TimelineDayCell.identifier, for: indexPath) as? TimelineDayCell
cell?.configure(with: testRecord)
cell?.dayLabel.text = String(indexPath.section)+","+String(indexPath.row)
return cell
})
return dataSource
}
func configureDataSource() {
self.collectionView!.register(TimelineDayCell.nib, forCellWithReuseIdentifier: TimelineDayCell.identifier)
}
func applySnapshot(animatingDifferences: Bool = true) {
// 2
var snapshot = DataSourceSnapshot()
for (ymd,records) in data {
snapshot.appendSections([ymd])
snapshot.appendItems(records,toSection: ymd)
}
// This is where the error occurs.
dataSource.apply(snapshot, animatingDifferences: animatingDifferences)
}
}
Но я получаю эту ошибку:
*** Завершение работы приложения из-за неперехваченного исключения "NSInternalInconsistencyException", причина: "запрос количества элементов в разделе 0, когда в представлении коллекции только 0 разделов"
Если я смотрю на данные, я вижу, что все они заполняются правильно, и когда я распечатываю snapshot.sectionIdentifiers, он дает мне все эти объекты YearMonthDay. Но почему-то dataSource видит 0 секций?
Я думаю, что для обычного источника данных я бы просто реализовал метод делегата - numberOfSections, но так как это источник данных, который можно различить, я не уверен, что делать...
Редактировать:
данные из делегата - это словарь этого типа: [YearMonthDay:[TestRecord]]. Вот как это выглядит в распечатанном виде
▿ 7 elements
▿ 0 : 2 elements
▿ key : <YearMonthDay: 0x600000e880f0>
▿ value : 1 element
▿ 0 : TestRecord
- identifier : 5D05C73D-8863-47E3-B1E5-3331791A3FB8
- type : SweatNetOffline.RecordType
- progression : 1
▿ timeStamp : 2020-10-16 04:56:59 +0000
- timeIntervalSinceReferenceDate : 624517019.639298
▿ 1 : 2 elements
▿ key : <YearMonthDay: 0x600000e89ec0>
▿ value : 1 element
▿ 0 : TestRecord
- identifier : C40F5884-AABF-43C8-9921-95DD1423AC4D
- type : SweatNetOffline.RecordType
- progression : 1
▿ timeStamp : 2020-10-22 04:56:59 +0000
- timeIntervalSinceReferenceDate : 625035419.639274
▿ 2 : 2 elements
▿ key : <YearMonthDay: 0x600000e88cf0>
▿ value : 1 element
▿ 0 : TestRecord
- identifier : 5EE70ABF-4C4D-4FB5-A850-3D0081D91D0D
- type : SweatNetOffline.RecordType
- progression : 2
▿ timeStamp : 2020-10-20 04:56:59 +0000
- timeIntervalSinceReferenceDate : 624862619.639284
▿ 3 : 2 elements
▿ key : <YearMonthDay: 0x600000e8a0a0>
▿ value : 1 element
▿ 0 : TestRecord
- identifier : 59152DCA-63EC-4EBF-ACDB-B45FA5E85EED
- type : SweatNetOffline.RecordType
- progression : 2
▿ timeStamp : 2020-10-18 04:56:59 +0000
- timeIntervalSinceReferenceDate : 624689819.639291
▿ 4 : 2 elements
▿ key : <YearMonthDay: 0x600000e89890>
▿ value : 1 element
▿ 0 : TestRecord
- identifier : 0E12D3D6-0650-41A6-AC12-EB75EFA0A151
- type : SweatNetOffline.RecordType
- progression : 0
▿ timeStamp : 2020-10-26 04:56:59 +0000
- timeIntervalSinceReferenceDate : 625381019.638627
▿ 5 : 2 elements
▿ key : <YearMonthDay: 0x600000e89e60>
▿ value : 1 element
▿ 0 : TestRecord
- identifier : 99A929C4-B94B-4F8F-8C6D-2C356D778D95
- type : SweatNetOffline.RecordType
- progression : 2
▿ timeStamp : 2020-10-24 04:56:59 +0000
- timeIntervalSinceReferenceDate : 625208219.639251
▿ 6 : 2 elements
▿ key : <YearMonthDay: 0x600000e89f20>
▿ value : 1 element
▿ 0 : TestRecord
- identifier : EF6EB971-504B-4587-8038-FB8C3FD7ACDC
- type : SweatNetOffline.RecordType
- progression : 1
▿ timeStamp : 2020-10-14 04:56:59 +0000
- timeIntervalSinceReferenceDate : 624344219.639307
1 ответ
Я не очень хорошо знаком с этим новым способом создания collectionView, но считаю, что проблема может быть связана с этой строкой кода.
snapshot.appendSections([ymd])
Почему вы передаете здесь массив для каждой итерации цикла For? Это нужно сделать один раз, не так ли?
for (ymd,records) in data {
snapshot.appendSections([ymd])
snapshot.appendItems(records,toSection: ymd)
}
к
snapshot.appendSections(Array(data.keys))
for (ymd,records) in data {
snapshot.appendItems(records,toSection: ymd)
}