基于 DiffableDataSource 的 UITableViewController 和 UICollectionViewController。
将以下内容添加到你的 Package.swift
的依赖项中
.package(url: "https://github.com/FelixHerrmann/FHDiffableViewControllers.git", from: "x.x.x")
按照此处所示,将包添加到你的项目中。
下载 Sources 文件夹中的文件并将它们拖到你的项目中。
如果你使用 Swift 包管理器,你必须使用 import FHDiffableViewControllers
将 FHDiffableViewControllers 导入到你的文件中。
现在你可以从 FHDiffableTableViewController
和 FHDiffableCollectionViewController
继承你的视图控制器类。
但首先你需要一个 SectionIdentifier
和 ItemIdentifier
,它们将被用于泛型类型。这两种类型都必须符合 Hashable
。
enum Section {
case main, detail
}
struct Item: Hashable {
var title: String
}
建议使 item 符合
Identifiable
,因为如果数据源中存在重复项,应用程序会崩溃!
这些类可以这样被子类化
class TableViewController: FHDiffableTableViewController<Section, Item> {
override var cellProvider: UITableViewDiffableDataSource<Section, Item>.CellProvider {
return { tableView, indexPath, item in
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = item.title
return cell
}
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
applySnapshot(animatingDifferences: false) {
FHSection(.main) {
Item(title: "First Item")
Item(title: "Second Item")
}
FHSection(.detail) {
Item(title: "Third Item")
}
}
}
}
必须覆盖 cellProvider,因为默认实现会引发致命错误。在你第一次调用
applySnapshot(_:)
之前,不要忘记注册单元格!
单元格选择可以这样实现
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = dataSource.itemIdentifier(for: indexPath)
/*do your actions with the selected item*/
}
为了使用自定义 header 或 footer 视图,必须覆盖 supplementaryViewProvider
属性。
override var supplementaryViewProvider: UICollectionViewDiffableDataSource<Section, Item>.SupplementaryViewProvider? {
return { collectionView, kind, indexPath in
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "customHeader", for: indexPath) as? CustomHeader
switch self.dataSource.snapshot().sectionIdentifiers[indexPath.section] {
case .main:
headerView?.backgroundColor = .systemGreen
case .detail:
headerView?.backgroundColor = .systemPink
}
return headerView
}
}
在你第一次调用 applySnapshot(_:)
之前,不要忘记注册 supplementary 视图!
collectionView.register(CustomHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "customHeader")
如果你想更改标题创建的行为,或者你想使用 section index titles 和其他功能,你必须对相应的数据源进行子类化。 对于 table view,它可能看起来像这样
class CustomDataSource: UITableViewDiffableDataSource<Section, Item> {
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch snapshot().sectionIdentifiers[section] {
case .main:
return "Main"
case .detail:
return "Detail"
}
}
}
对 collection view 使用
UICollectionViewDiffableDataSource
。
为了在我们的视图控制器中使用它,我们必须创建一个它的 lazy var 并用它覆盖 dataSource
属性。
lazy var customDataSource = CustomDataSource(tableView: tableView, cellProvider: cellProvider)
override var dataSource: UITableViewDiffableDataSource<Section, Item> {
return customDataSource
}
你不必强制使用 applySnapshot(_:)
与 FHDiffableDataSourceSection
数组结合来将快照应用到你的 dataSource
。 你可以覆盖 applySnapshot(_:)
来更改它的行为,创建你自己的 applySnapshot()
方法,或者手动执行,如下所示
var snapshot = FHSnapshot()
snapshot.appendSections([.main, .detail])
snapshot.appendItems([Item(title: "Main Item")], toSection: .main)
snapshot.appendItems([Item(title: "Detail Item")], toSection: .detail)
dataSource.apply(snapshot, animatingDifferences: true, completion: nil)
除了传统的数组方式,还有 Section 和 Item 创建的结果构建器。
applySnapshot([
FHSection(.main, items: [
Item(title: "First Item"),
Item(title: "Second Item"),
]),
FHSection(.detail, items: [
Item(title: "Third Item"),
]),
])
applySnapshot {
FHSection(.main) {
Item(title: "First Item")
Item(title: "Second Item")
}
FHSection(.detail) {
Item(title: "Third Item")
}
}
FHConstraints 在 MIT 许可证下可用。 有关更多信息,请参阅 LICENSE 文件。