背景
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<Section, Note>!
override func viewDidLoad() {
self.dataSource = getDataSource()
}
func getDataSource() -> UITableViewDiffableDataSource<Section, Note>? {
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<SectionIdentifierType, ItemIdentifierType>.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<Section, Note>()
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<NoteSection, 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()
// 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<NoteSection, 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<NoteSection, Note>()
snapshot.appendSections([.today])
snapshot.appendItems(noteList)
self.dataSource.apply(snapshot, animatingDifferences: false, completion: nil)
}
}
网友评论