在 iOS 13 中 Apple 為 UITableView 和 UICollectionView 引入了 DiffableDataSource,讓開發者可以更簡單高效的實現 UITableView、UICollectionView 的局部數據刷新。新的刷新的方法為 apply,通過使用 apply ...
在 iOS 13 中 Apple 為 UITableView 和 UICollectionView 引入了 DiffableDataSource,讓開發者可以更簡單高效的實現 UITableView、UICollectionView 的局部數據刷新。新的刷新的方法為 apply,通過使用 apply 方法無需計算變更的 indexPaths,也無需調用 reload,即可安全地在主線程或後臺線程更新 UI, 僅需簡單的將需要變更後的數據通過 NSDiffableDataSourceSnapshot 計算出來。
1、使用 DiffableDataSource 配置當前 UITableView 的數據源。
func getDataSource() -> UITableViewDiffableDataSource<Section, Note>? { return UITableViewDiffableDataSource(tableView: self.tableView) { (tableView, indexPath, note) -> UITableViewCell? in let cell = UITableViewCell() cell.textLabel?.text = note.content return cell } }
2、在需要刷新的時候,使用 DataSourceSnapshot 處理變更後的數據源,其有 append、delete、move、insert 等方法。DiffableDataSource 通過調用自身 apply 方法將 DataSourceSnapshot 變更後的數據更新同步到 UITableView。
func updateData(_ noteList: [Note]) { var snapshot = NSDiffableDataSourceSnapshot<Section, Note>() snapshot.appendSections([.today]) snapshot.appendItems(noteList) self.dataSource.apply(snapshot, animatingDifferences: false, completion: nil) }
原理:使用snapshot對dataSource進行差異化比對,進行動態更新。避免了之前的複雜的維護過程
實例代碼
import UIKit enum Section { case today } struct Note : Hashable { var idx : Int var content : String } class ViewController: UIViewController { private var dataSource: UITableViewDiffableDataSource<Section, Note>! 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() let noteList = [ Note(idx:0, content:"0"), Note(idx:1, content:"1"), Note(idx:2, content:"2"), Note(idx:3, content:"4") ] self.dataSource = getDataSource() updateData(noteList) } func getDataSource() -> UITableViewDiffableDataSource<Section, Note>? { 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<Section, Note>() snapshot.appendSections([.today]) snapshot.appendItems(noteList) self.dataSource.apply(snapshot, animatingDifferences: false, completion: nil) } }