Search code examples
iosuitableviewios13

UITableViewDiffableDataSource: how to get a section index


I'm trying to adopt the new iOS 13 UITableViewDiffableDataSource and I've hit a snag; I can't work how to implement

func sectionIndexTitles(for tableView: UITableView) -> [String]?

That's a data source method, not a delegate method. So, now that the data source is the UITableViewDiffableDataSource, it needs to implement that method. But it doesn't.

I tried subclassing UITableViewDiffableDataSource and adding an implementation of sectionIndexTitles, but my implementation was never called:

class MyDataSource : UITableViewDiffableDataSource<String,String> {
    func sectionIndexTitles(for tableView: UITableView) -> [String]? {
        return self.snapshot().sectionIdentifiers // not called
    }
}

Has anyone solved this one? I'll file it as a bug just in case.


Solution

  • You need to subclass UITableViewDiffableDataSource and then overwrite

    func sectionIndexTitles(for tableView: UITableView) 
    

    by yourself.

    To enable the index' functionality though, you have to also overwrite

    func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int)
    

    Here is an example how I implemented it:

    import UIKit
    import MediaPlayer
    
    class TableViewDiffableDataSource: UITableViewDiffableDataSource<String, MPMediaItemCollection> {
        var sectionTitles = [String]()
    
        override func sectionIndexTitles(for tableView: UITableView) -> [String]? {
            return sectionTitles
        }
    
        override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
            return sectionTitles[section]
        }
    
        override func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
            return sectionTitles.firstIndex(of: title) ?? 0
        }
    }
    

    Credits go to Steve Breen, who led me in the right direction.