【问题标题】:UICollectionViewDiffableDataSource: Request for number of items in section 0 when there are only 0 sections in the collection viewUICollectionViewDiffableDataSource:当collection view只有0个section时,请求section 0的item数
【发布时间】:2020-10-24 02:33:36
【问题描述】:

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

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 个部分。

这是我的 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 部分中的项目数”

如果我查看数据,我可以看到所有数据都已正确填充,当我打印出 snapshot.sectionIdentifiers 时,它会为我提供所有这些 YearMonthDay 对象。但不知何故,数据源看到了 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

【问题讨论】:

  • 请显示数据,即dataForTimelineView的结果。
  • @matt 我刚才在我的编辑中展示了它

标签: ios swift uicollectionview uicollectionviewdiffabledatasource


【解决方案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)
  }

【讨论】:

  • 我试过 snapshot.appendSections([Array(data.keys)]) 只做一次,然后逐节做项目。但是,会出现同样的问题。虽然我不明白为什么逐节做这个会不好?只能做一次吗?
  • 嗯,我明白了。你在 configureHierarchy() 中放了什么?
  • 您使用 DataSourceSnapshot 与 NSDiffableDataSourceSnapshot 有什么原因吗?
  • 您在顶部看到我的 DataSourceSnapshot 的文件私有类型别名了吗?我从本教程中了解到这一点 - raywenderlich.com/…。我可以尝试不这样做。 configureHierarchy 将我的集合视图布局设置为自定义布局。它的名字可能很糟糕
  • 在该 applySnapshot 函数中使用 var snapshot = NSDiffableDataSourceSnapshot&lt;YearMonthDay,TestRecord&gt;() 似乎会导致相同的错误。我会做一个项目 repo,以便您可以尝试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-23
  • 2013-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多