UITableViewDiffableDataSource的使用

背景

UITableViewDiffableDataSource 出现的原因,主要是列表数据在刷新时。若使用reloadData方法,会进行所有数据的刷新(明显比较耗资源);若要进行局部刷新,reloadRows或者reloadSection等,这部分的数据刷新需要程序员自己进行比对(过程比较复杂,且容易出错)

使用方式

1.准备数据源

数据类型必选是Hashable类型

// Model.swift
enum Section {
  case today
}

struct Note: Hashable {
  var id: Int
  var content: String
}

2.使用UITableViewDiffableDataSource

// UIViewController.swift
// UITableViewDiffableDataSource泛型第一个参数是section类型,第二个参数是item类型
private var dataSource: UITableViewDiffableDataSource!

override func viewDidLoad() {
  self.dataSource = getDataSource()
}

func getDataSource() -> UITableViewDiffableDataSource? {
  return UITableViewDiffableDataSource(tableView: self.tableView) {
    (tableView, index, note) -> UITableViewCell? in 
      let cell = UITableViewCell()
        cell.textLabel?.text = note.content
    
        return cell
  }
}

UITableViewDiffableDataSource的初始化方法

public init(tableView: UITableView, cellProvider: @escaping UITableViewDiffableDataSource.CellProvider)

其中CellProvider定义如下

public typealias CellProvider = (UITableView, IndexPath, ItemIdentifierType) -> UITableViewCell?

3.更新数据

// UIViewController.swift
override func viewDidLoad() {
  let noteList = [
    Note(id:0, content:"0"),
    Note(id:1, content:"1"),
    Note(id:2, content:"2"),
    Note(id:3, content:"4")
  ]
  updateData(noteList)
}

func updateData(_ noteList: [Note]) {
  var snapshot = NSDiffableDataSourceSnapshot()
  snapshot.appendSections([.today])     // 对应的section
  snapshot.appendItems(noteList)            // 对应的item
  self.dataSource.apply(snapshot, animatingDifferences: false, completion: nil)
}

主要靠出入snapshot让dataSource进行数据更新。需要注意的是,初始化数据和更新数据都是用到用到snapshot

原理

使用snapshot对dataSource进行差异化比对,进行动态更新。避免了之前的复杂的维护过程

完整代码

// Model.swift
import Foundation

enum Section {
    case today
}

struct Note: Hashable {
    var id: Int
    var content: String
}
import UIKit

class ViewController: UIViewController {
    private var dataSource: UITableViewDiffableDataSource!
    
    private lazy var tableView: UITableView = {
        let tableView = UITableView()
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: String(describing: UITableViewCell.self))
        
        self.view.addSubview(tableView)
        
        return tableView
    }()
    
    override func loadView() {
        super.loadView()
        
        self.tableView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        self.tableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
        self.tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
        self.tableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let noteList = [
          Note(id:0, content:"0"),
          Note(id:1, content:"1"),
          Note(id:2, content:"2"),
          Note(id:3, content:"4")
        ]
      
        self.dataSource = getDataSource()
        updateData(noteList)
        
    }
    
    func getDataSource() -> UITableViewDiffableDataSource? {
        return UITableViewDiffableDataSource(tableView: self.tableView) { (tableView, indexPath, note) -> UITableViewCell? in
            let cell = UITableViewCell()
            cell.textLabel?.text = note.content
            return cell
        }
    }
    
    func updateData(_ noteList: [Note]) {
        var snapshot = NSDiffableDataSourceSnapshot()
        snapshot.appendSections([.today])
        snapshot.appendItems(noteList)
        self.dataSource.apply(snapshot, animatingDifferences: false, completion: nil)
    }
}

你可能感兴趣的:(UITableViewDiffableDataSource的使用)