Section titles with UITableViewDiffableDataSource

How can I display the header titles in a UITableView when using the new UITableViewDiffableDataSource? I can’t find anything in the documentation for it or in NSDiffableDataSourceSnapshotReference.

Same issue. UITableViewDiffableDataSource implements UITableViewDataSource, but it’s a public class. So you can’t override the methods for headers and footers... maybe a bug? Maybe it’s supposed to be an open class instead of public?

There's no way to do that right now. I've opened a bug (FB6277179) in order to have them add this to the API. UITableViewDiffableDataSource is awesome, would be sad to not being able to use it over such a critical shortcoming...

UITableViewDiffableDataSource is now an open class in iOS 13 beta 3 but adding UITableViewDataSource methods doesn't work.

I don't see any updates in beta 4 or beta 5. Any suggestions how to deal?

Yes, don't use UITableViewDiffableDataSource. Clearly they did a half baked job that will only be useful for a handful of use cases. At this point I doubt they'll add this before iOS 13 ships.


Axiously waiting for the WWDC 20 "What's new in diffable sources" session.

Could it be possible to override the UITableViewDiffableDataSource's implementation of the titleForSection callback? Maybe using some crazy obj-c runtime stuff?

If they don't add an easy way to do titles, I'm just gonna write it myself, it's such a great idea, but if it's not a complete execution, then it's not worth using.

Same problem with sectionIndexTitles. It doesn't implement it and you can't get it to work by subclassing or anything like that. So I can't adopt UITableViewDiffableDataSource.

As of Xcode 11 Beta 6, it's now possible for implement a subclass of UITableViewDiffableDataSource and override titleForSectionAtIndex.


This is however at odds with the 'snapshot' paradigm of the diffable data source. For converting the index to the Section identifier, i'd hope there'd be a more perfomant way of providing titles than calling 'snapshot()' and querying its sectionIdentifiers on every call.

Still doesn't solve the problem with sectionIndexTitles. The index now appears down the right side of the table but clicking on it doesn't actually do anything.

After you init

self.dataSource
to a
UITableViewDiffableDataSource
(which sets itself to the
tableView.dataSource
) set the
tableView.dataSource
back to self, i.e. the
UITableViewController
subclass. Now in your
numberOfSectionsInTableView
and
numberOfRowsInSection
methods forward those to
self.dataSource
and return its info (this is the composition pattern). Now your
UITableViewController
just implements its section titles as normal since it is the table's data source.


I believe

UITableViewDiffableDataSource
should not be setting itself as the dataSource if one is already set but I guess they designed it to work in the least error prone way because with
UITableViewController
added to a storyboard its already set.


If you do it this way then it makes sense why the class wasn't open in the early iOS 13 betas.

The secret is on Data Model, I think that you must have the title for the section on your Model.

Imagine the following solution:

You have this Section Model:

struct Section: Hashable {
    let name: String
    let listOfItems: [String]
    let uuid = UUID()
}

So on your view controller, you will have the dataSource like that:

var dataSource: UITableViewDiffableDataSource<Section, String>

Then, on implementation of your updateDataSource you will use like that:

private func updateDataSource(sections: [Section]) {
    var snapshot = NSDiffableDataSourceSnapshot<Section, String>()     
    
    snapshot.appendSections(sections)
     
    for section in sections {
      snapshot.appendItems(section.listOfItems, toSection: section)
    }
     
    dataSource.apply(snapshot)
 }

So, to set the section title I have used the implementation of tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? creating a label and returning it, to set the text of the label I have used the dataSource function sectionIdentifier(for index: Int) -> SectionIdentifierType?, unfortunatelly this function is available only on iOS, tvOS 15.0 or later.

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let label = UILabel(frame: CGRect(x: 0, y: 0, width: 60, height: 20))
    label.text = dataSource.sectionIdentifier(for: section)?.name
    return label
}

The function sectionIdentifier(for index: Int) -> SectionIdentifierType? returns the type of the Section Identifier defined on dataSource, in this example the type of the section identifier is Section, so, just use the name property to set the name of your section.

I hope that this explanation could help you.

🤘🏼🤘🏼😉😉

Section titles with UITableViewDiffableDataSource
 
 
Q