【Swift】UITableViewDiffableDataSource的用法

  在 iOS 13 中 Apple 爲 UITableView 和 UICollectionView 引入了 DiffableDataSource,讓開發者能夠更簡單高效的實現 UITableView、UICollectionView 的局部數據刷新。新的刷新的方法爲 apply,經過使用 apply 方法無需計算變動的 indexPaths,也無需調用 reload,便可安全地在主線程或後臺線程更新 UI, 僅需簡單的將須要變動後的數據經過 NSDiffableDataSourceSnapshot 計算出來。安全

  一、使用 DiffableDataSource 配置當前 UITableView 的數據源。app

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
        }
    }

  二、在須要刷新的時候,使用 DataSourceSnapshot 處理變動後的數據源,其有 append、delete、move、insert 等方法。DiffableDataSource 經過調用自身 apply 方法將 DataSourceSnapshot 變動後的數據更新同步到 UITableView。ide

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進行差別化比對,進行動態更新。避免了以前的複雜的維護過程spa

  實例代碼

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)
    }
}
相關文章
相關標籤/搜索