0

I have a data source like so

   fileprivate func makeRecordsDataSource() -> RecordsDataSource {
        let dataSource = RecordsDataSource(
            collectionView: recordsCollectionView,
            cellProvider: { (collectionView, indexPath, recordItem) ->
              UICollectionViewCell? in
                switch recordItem.type {
                case .Rep:
                    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: RepRecordCell.identifier, for: indexPath) as? RepRecordCell
                    cell!.configure(with: recordItem)
                    return cell
                case .Image:
                    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ImageRecordCell.identifier, for: indexPath) as? ImageRecordCell
                    cell!.configure(with: recordItem)
                    return cell
                case .Video:
                    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: VideoRecordCell.identifier, for: indexPath) as? VideoRecordCell
                    cell!.configure(with: recordItem)
                    return cell
                case .Text:
                    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TextRecordCell.identifier, for: indexPath) as? TextRecordCell
                    cell!.configure(with: recordItem)
                    return cell
                }
            })
        return dataSource
    }

In my view controller I have

private lazy var recordsDataSource = makeRecordsDataSource()

Then a function to apply a snapshot to my data source....

func applyRecordsSnapshot(days:[YearMonthDay]) {
    var snapshot = RecordsDataSourceSnapshot()
    snapshot.appendSections(days)
    var i = 0
    for ymd in days {
        sectionMap[ymd] = i
        snapshot.appendItems(ymd.recordItems,toSection: ymd)
        i += 1
    }
    recordsDataSource.apply(snapshot, animatingDifferences: false)
}

in the debugger, when I look at the snapshot.numberOfItems, I see 4, so there are 4 sections... But for some reason the closure cellProvider never gets called when I put breakpoints inside of it. Wouldn't it get called once for each cell in the snapshot?

BigBoy1337
  • 4,735
  • 16
  • 70
  • 138
  • Are there any "cells" in the snapshot? Are the cells actually appearing in the interface? – matt Jun 23 '22 at 02:39
  • @matt no cells are appearing in the interface. I believe there are 4 "cells" because the snapshot.numberOfItems is 4 – BigBoy1337 Jun 23 '22 at 23:48

2 Answers2

1

I’ve been learning the diffable data source and cell providers APIs this week and from my experience, it looks like you’re doing things correctly.

I did notice that you’re using the traditional dequeueReusableCell(withReuseIdentifier:for:) method. In the past I’ve had similar issues with UITableView when I didn’t register my cell.

collectionView.register(RepRecordCell.self, forCellWithReuseIdentifier: RepRecordCell.identifier)

It’s a one-liner and often separate from cell creation so maybe you are doing this and just omitted that part of for clarity.

Cell Registration in iOS 14.0

In my projects I’ve been using the new UICollectionView.CellRegistration API and it’s much cleaner and all in one place. Plus, no more need for reuseIdentifiers, pre-registration, and optional casting. Here’s how I configure my collectionView and dataSource:

let makeItemCell = UICollectionView.CellRegistration<UICollectionViewCell, Item> { cell, indexPath, item in
    cell.contentConfiguration = UIHostingConfiguration {
        ItemView(item) // A SwiftUI View
    }
}

let collectionView: UICollectionView = // 
let dataSource = UICollectionViewDiffableDataSource<Int, Item>(collectionView: collectionView) { collectionView, indexPath, item in
    collectionView.dequeueConfiguredReusableCell(using: makeItemCell, for: indexPath, item: item)
}
Shawn Throop
  • 1,281
  • 1
  • 13
  • 28
  • Do you know if the CellRegistration API is available for Table Views as well as collection views? I can't find that information anywhere.. – BigBoy1337 Aug 24 '22 at 23:54
  • It appears like UITableView is on the way out. There is a way to achieve the same styling/functionality using the UICollectionView and the [sectionProvider initialiser of UICollectionViewCompositionalLayout](https://developer.apple.com/documentation/uikit/uicollectionviewcompositionallayout/3199214-init) in tandem with [NSCollectionLayoutSection.list(using:layoutEnvironment:)](https://developer.apple.com/documentation/uikit/nscollectionlayoutsection/3600714-list). – Shawn Throop Aug 25 '22 at 04:13
  • There are some helpful examples in the [Implementing Modern Collection Views](https://developer.apple.com/documentation/uikit/views_and_controls/collection_views/implementing_modern_collection_views) sample project, specifically in the Lists folder. UITableView was my jam back in the day but I've been pleasantly surprised by the flexibly of the newer compositional layouts API, even for single column layouts. – Shawn Throop Aug 25 '22 at 04:18
0

Old question but for me the problem was that I was setting all these before viewDidLoad so the collectionView wasn't ready. Check on what part of the lifecycle you're setting things, should be on the viewDidLoad or after.

D-Mx
  • 513
  • 5
  • 12