A-A+

iOS开发之DiffableDataSource

博客主机

在 iOS 13 中 Apple 为 UITableView 和 UICollectionView 引入了 DiffableDataSource,让开发者可以更简单高效的实现 UITableView、UICollectionView 的局部数据刷新。新的刷新的方法为 apply,通过使用 apply 方法无需计算变更的 indexPaths,也无需调用 reload,即可安全地在主线程或后台线程更新 UI, 仅需简单的将需要变更后的数据通过 NSDiffableDataSourceSnapshot 计算出来。下面以 UITableView 为例进行讲解。

实现步骤

  • 使用 DiffableDataSource 配置当前 UITableView 的数据源。
var dataSource: UITableViewDiffableDataSource<Section, City>!

override func viewDidLoad() {
    super.viewDidLoad()

    dataSource = UITableViewDiffableDataSource
        <Section, City>(tableView: tableView) {
            (tableView: UITableView, indexPath: IndexPath,
            city: City) -> UITableViewCell? in
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
            cell.textLabel?.text = city.name
            return cell
    }

    dataSource.defaultRowAnimation = .fade
}
  • 在需要刷新的时候,使用 DataSourceSnapshot 处理变更后的数据源,其有 append、delete、move、insert 等方法。DiffableDataSource 通过调用自身 apply 方法将 DataSourceSnapshot 变更后的数据更新同步到 UITableView。
enum Section: CaseIterable {
    case main
}

var snapshot = NSDiffableDataSourceSnapshot<Section, City>()
snapshot.appendSections([.main])
snapshot.appendItems(filteredCities, toSection: .main)
dataSource.apply(snapshot, animatingDifferences: true)
  • 为了确保 Diff 生效,数据源的 Model 必须具有唯一 Identifier,且遵循 Hashable 协议。
struct City: Hashable {
    let name: String
    let identifier = UUID()

    func hash(into hasher: inout Hasher) {
        hasher.combine(identifier)
    }

    static func ==(lhs: City, rhs: City) -> Bool {
        return lhs.identifier == rhs.identifier
    }

    func contains(query: String?) -> Bool {
        guard let query = query else { return true }
        guard !query.isEmpty else { return true }
        return name.contains(query)
    }
}
  • 点击事件中,获取 cell 的方式也和之前不一样。
extension ViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if let city = dataSource.itemIdentifier(for: indexPath) {
            print("选择了\(city.name)")
        }
    }
}

源代码

前面介绍的是 UITableView 的关键使用步骤,UIColletionView 使用类似,完整案例详见下面的链接:

  1. UITableView案例
  2. UICollectionView案例

给我留言

Copyright © ios教程,苹果粉丝,苹果资讯,ios入门教程,ios学习,ios程序员,ios视频教程,ios粉丝网 保留所有权利.   Theme  Ality

用户登录