I am trying to make a timeline where each section is a day and each day has many items (records). Here is my section (day) class:
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
}
}
}
}
As you can see I am adding year month and day attributes to my sections and using them to make each one "washable" so hopefully there will be only 1 section for each day at most.
Here is my collectionViewController...
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)
}
}
But I get this crash error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'request for number of items in section 0 when there are only 0 sections in the collection view'
If I look at data, I can see that all of it is being populated correctly and when I print out snapshot.sectionIdentifiers it gives me all of those YearMonthDay objects. But somehow the dataSource is seeing 0 sections?
I think for a normal data source, I would just implement the delegate method - numberOfSections but since this is a diffable data source Im not sure what to do...
from UICollectionViewDiffableDataSource: Request for number of items in section 0 when there are only 0 sections in the collection view
No comments:
Post a Comment