UITableViewDiffableDataSource:如何设置部分 header 标题?

UITableViewDiffableDataSource: how to set section header titles?

我正在尝试在 UITableViewController.

中使用新的 UITableViewDiffableDataSource 设置一个 UITableView 部分

除了设置部分 header 标题外,一切似乎都正常。

根据 Apple 的文档,UITableViewDiffableDataSource 符合 UITableViewDataSource,所以我希望这是可能的。

我试过:

  1. 覆盖 tableView(_ tableView:, titleForHeaderInSection section:) 在 UITableViewController class
  2. subclassing UITableViewDiffableDataSource 并在 subclass
  3. 中实现 tableView(_ tableView:, titleForHeaderInSection section:)

但这两种方式都没有结果(Xcode 11 和 iOS13 beta 3)。

目前是否可以使用 UITableViewDiffableDataSource 设置 header 部分的标题?

更新:从 beta 8 开始,您现在可以在 UITableViewDiffableDataSource 子类中实现 tableView(_ tableView:, titleForHeaderInSection section:),它可以正常工作。

填充 header 标题的默认行为在数据源中一直有点奇怪。对于 UITableViewDiffableDataSource,Apple 似乎通过不提供默认 string-based 行为来承认这一点;但是,UITableViewDelegate 方法继续像以前一样工作。通过初始化并返回具有所需部分标题的 UILabel 并实施 tableView(_:heightForHeaderInSection:) 来管理所需的高度来实施 tableView(_:viewForHeaderInSection:)

提供关于@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
    }
}

self.dataSource 初始化为 UITableViewDiffableDataSource(将其自身设置为 tableView.dataSource)后,将 tableView.dataSource 设置回自身,即 UITableViewController子class。现在在你的 numberOfSectionsInTableViewnumberOfRowsInSection 方法中将它们转发给 self.dataSource 和 return 它的信息(这是组合模式)。现在您的 UITableViewController 只是正常实现其部分标题,因为它是 table 的数据源。

我认为 UITableViewDiffableDataSource 不应该将自己设置为数据源,如果已经设置的话,但我猜他们将其设计为以最不容易出错的方式工作,因为将 UITableViewController 添加到故事板已经设置好了。

如果你这样做,那么 class 在早期的 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 协议来控制显示为部分标题的内容。