Я пытаюсь настроить UITableView с разделами, используя новый UITableViewDiffableDataSource внутри UITableViewController.
Кажется, все работает нормально, кроме установки заголовков заголовков разделов.
Согласно документации Apple, UITableViewDiffableDataSource соответствует UITableViewDataSource, поэтому я ожидал, что это возможно.
Я пытался:
но оба пути не приводят к результату (Xcode 11 и iOS13 beta 3).
Есть ли в настоящее время способ установить заголовки разделов с помощью UITableViewDiffableDataSource?





Обновление: начиная с бета-версии 8, теперь вы можете реализовать tableView(_ tableView:, titleForHeaderInSection section:) в подклассе UITableViewDiffableDataSource, и он работает правильно.
Поведение по умолчанию для заполнения заголовка заголовка всегда было немного странным для источника данных. С UITableViewDiffableDataSource Apple, похоже, признает это, не предоставляя поведение на основе строк по умолчанию; однако методы UITableViewDelegate продолжают работать, как и прежде. Реализация tableView(_:viewForHeaderInSection:) путем инициализации и возврата UILabel с желаемым заголовком раздела и реализация tableView(_:heightForHeaderInSection:) для управления желаемой высотой работает.
Я разместил вопрос об этом на форумах разработчиков Apple здесь в маловероятной надежде, что инженер Apple увидит его.
Получается, что метод tableView(_:viewForHeaderInSection:) предоставляется UITableViewDelegate, а не UITableViewDataSource. Виноват!
Предоставление примера кода по объяснениям @particleman.
struct User: Hashable {
var name: String
}
enum UserSection: String {
case platinum = "Platinum Tier"
case gold = "Gold Tier"
case silver = "Silver Tier"
}
class UserTableViewDiffibleDataSource: UITableViewDiffableDataSource<UserSection, User> {
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
guard let user = self.itemIdentifier(for: IndexPath(item: 0, section: section)) else { return nil }
return self.snapshot().sectionIdentifier(containingItem: user)?.rawValue
}
}
Я только что использовал snapshot().sectionIdentifiers[section].rawValue
или немного более лаконично: sectionIdentifier(for: section)?.rawValue
После того, как вы инициируете self.dataSource в UITableViewDiffableDataSource (который устанавливает себя в tableView.dataSource), установите tableView.dataSource обратно в себя, то есть в подкласс UITableViewController. Теперь в ваших методах numberOfSectionsInTableView и numberOfRowsInSection перенаправьте их в self.dataSource и верните его информацию (это шаблон композиции). Теперь ваш UITableViewController просто реализует заголовки своих разделов как обычно, поскольку он является источником данных таблицы.
Я считаю, что UITableViewDiffableDataSource не должен устанавливать себя в качестве источника данных, если он уже установлен, но я думаю, они разработали его так, чтобы он работал с наименьшей вероятностью ошибок, потому что с добавлением UITableViewController в раскадровку он уже установлен.
Если вы сделаете это таким образом, то станет понятно, почему класс не был открыт в ранних бета-версиях iOS 13.
Предложу достаточно гибкое универсальное решение:
Объявите подкласс:
class StringConvertibleSectionTableViewDiffibleDataSource<UserSection: Hashable, User: Hashable>: UITableViewDiffableDataSource<UserSection, User> where UserSection: CustomStringConvertible {
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sectionIdentifier(for: section)?.description
}
}
Пример использования:
class ComitsListViewController: UITableViewController {
private var diffableDataSource = StringConvertibleSectionTableViewDiffibleDataSource<String, Commit>(tableView: tableView) { (tableView, indexPath, commit) -> UITableViewCell? in
let cell = tableView.dequeueReusableCell(withIdentifier: "Commit", for: indexPath)
cell.configure(with: commit)
return cell
}
}
Вы не ограничены только String мыслью. Вы можете контролировать, что отображать в качестве заголовка раздела, реализуя протокол description var of CustomStringConvertible для вашего типа раздела.
Я нацелен на iOS 13 и разрабатываю Xcode 11.4.1, и, к сожалению, похоже, что метод
tableView(_:viewForHeaderInSection:)недоступен для переопределения в расширенияхUITableViewDiffableDataSource?