Adrian
Adrian

Reputation: 16735

Creating a section title with UITableViewDiffableDataSource

I'm tinkering a bit with UITableViewDiffableDataSource and I'm able to get a tableView to load without issue. I'm trying to create section headers in the tableView, however I've encountered some flakey behavior.

The section enum enum defined as follows:

    enum AlertLevel: String, Codable, CaseIterable {
        case green = "green"
        case yellow = "yellow"
        case orange = "orange"
        case red = "red"
    }

This is my implementation for tableView(viewForHeaderInSection:)

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let label = UILabel()
        label.text = dataSource.snapshot().sectionIdentifiers[section].rawValue.capitalized
        label.textColor = UIColor.black

        return label
    }

That gives me 4 labels stacked in header cells at the top of my tableView.

I fired up Dash to RTFD and I saw tableView(titleForHeaderInSection:) is another way to skin that cat. So I threw this in, instead:

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return dataSource.snapshot().sectionIdentifiers[section].rawValue.capitalized
    }

I threw a breakpoint in and it never gets hit. So I implemented tableView(heightForHeaderInSection:) and the header gets updated, but no string displays for the header.

The table loads a LOT faster than it does "the old fashioned way" with IndexPaths (I'm using USGS earthquake database to learn TableViewDiffableDataSource), but I can't get the headers to show up.

Anyone got an idea of how to get sections working on a TableViewDiffableDataSource? I have a hard time believing they'd let something like this into the wild without such basic functionality, so I'm left to conclude I'm fouling something up...what, I don't know :)

Oh...and here's how I define my data source:

func makeDataSource() -> UITableViewDiffableDataSource<AlertLevel, Earthquake> {
    return UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, earthquake in
        let cell = tableView.dequeueReusableCell(withIdentifier: self.reuseID, for: indexPath)
        cell.textLabel?.text = earthquake.properties.title
        cell.detailTextLabel?.text = earthquake.properties.detail

        return cell
    }
}

Upvotes: 6

Views: 2203

Answers (1)

Tung Fam
Tung Fam

Reputation: 8167

I was able to do that by subclassing the UITableViewDiffableDataSource class like this:

class MyDataSource: UITableViewDiffableDataSource<Section, Int> {

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        let section = self.snapshot().sectionIdentifiers[section]
        return section.header
    }
}

where your Section is:

enum Section: Int {
    case one

    var header: String {
        switch self {
        case .one: return "Header One"
        }
    }
}

and then assign your newly created data source this way:

dataSource = MyDataSource<Section, Int>

meaning, you don't need to use UITableViewDiffableDataSource anymore, but use a subclassed MyDataSource class.

Upvotes: 8

Related Questions