UICollectionViewDiffableDataSource:当集合视图中只有 0 个部分时,请求第 0 部分中的项目数 [英] UICollectionViewDiffableDataSource: Request for number of items in section 0 when there are only 0 sections in the collection view

查看:34
本文介绍了UICollectionViewDiffableDataSource:当集合视图中只有 0 个部分时,请求第 0 部分中的项目数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制定一个时间表,其中每个部分都是一天,每一天都有许多项目(记录).这是我的部分(日)课:

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
            }
        }
    }
}

如您所见,我正在向我的部分添加年月日属性,并使用它们使每个部分可清洗".所以希望每天最多只有 1 个部分.

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.

这是我的 collectionViewController...

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)
    }
}

但我收到此崩溃错误:

*** 由于未捕获的异常NSInternalInconsistencyException"而终止应用,原因:当集合视图中只有 0 个部分时,请求第 0 部分中的项目数"

*** 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'

如果我查看数据,我可以看到所有数据都被正确填充,当我打印出 snapshot.sectionIdentifiers 时,它会为我提供所有 YearMonthDay 对象.但不知何故,数据源看到了 0 个部分?

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?

我认为对于普通数据源,我只会实现委托方法 - numberOfSections 但由于这是一个可区分的数据源,我不知道该怎么做...

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...

来自委托的数据是这种类型的字典:[YearMonthDay:[TestRecord]].这是打印出来的样子

data from the delegate is a dictionary of this type: [YearMonthDay:[TestRecord]]. Here is what it looks like when printed out

▿ 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

推荐答案

我对这种构造 collectionView 的新方法不是很熟悉,但我相信问题可能出在这行代码上

I'm not super familiar with this new way of constructing a collectionView, but I believe the problem could be due to this line of code

snapshot.appendSections([ymd])

为什么要在此处为​​ For 循环中的每次迭代传入一个数组?这应该做一次,不是吗?

Why are you passing in an array here, for each iteration in the For loop? This should be done once, should it not?

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)
  }

这篇关于UICollectionViewDiffableDataSource:当集合视图中只有 0 个部分时,请求第 0 部分中的项目数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆