UICollectionViewDiffableDataSource 的简单使用

191 阅读1分钟
import UIKit

  


class DiffableCollectionViewController: UIViewController {

    private var dataSource: UICollectionViewDiffableDataSource<Section, MyModel>! = nil

  


    // 这是即将用来展示的models

    private lazy var mainModels = [MyModel(title: "Item1"),

                                   MyModel(title: "Item2"),

                                   MyModel(title: "Item3"),

                                   MyModel(title: "Item4"),

                                   MyModel(title: "Item5"),

                                   MyModel(title: "Item6"),

                                   MyModel(title: "Item7"),

                                   MyModel(title: "Item8")]

    

    // tableView

    private lazy var collectionView: UICollectionView = {

        let layout = UICollectionViewFlowLayout()

        

        layout.itemSize = CGSize(width: 80, height: 80)

        layout.scrollDirection = .vertical

        

        let collection = UICollectionView(frame: .zero, collectionViewLayout: layout)

        collection.translatesAutoresizingMaskIntoConstraints = false

        collection.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "identifier")

        collection.delegate = self

        collection.backgroundColor = UIColor.lightGray

        return collection

    }()

    

    lazy var collectionHeight = collectionView.heightAnchor.constraint(equalToConstant: 170)

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupNav()

        setupTableView() // 设置tableView UI

        setupDataSource() // 设置tableView的dataSource

        applySnapshot() // 给dataSource设置snapshot

    }

    

    func setupTableView() {

        view.addSubview(collectionView)

        NSLayoutConstraint.activate([

            collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),

            collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),

            collectionView.topAnchor.constraint(equalTo: view.topAnchor, constant: 200),

            collectionHeight

        ])

    }

    

    func setupNav() {

        let addItems = UIBarButtonItem(title: "Add", style: .plain, target: self, action: #selector(insertData))

        let deleteItems = UIBarButtonItem(title: "Delete", style: .plain, target: self, action: #selector(deleteData))

  


        self.navigationItem.rightBarButtonItems = [addItems, deleteItems]

    }

    

    func setupDataSource() {

        dataSource = UICollectionViewDiffableDataSource<Section, MyModel>

            .init(collectionView: self.collectionView, cellProvider: {(collectionView, indexPath, model) -> UICollectionViewCell? in

                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "identifier", for: indexPath)

                cell.backgroundColor = model.backgroundColor

                return cell

            })

    }

    

    func applySnapshot() {

        // 往snapshot里插入sections和items

        var snapshot = NSDiffableDataSourceSnapshot<Section, MyModel>()

        snapshot.appendSections([.main])

        snapshot.appendItems(mainModels, toSection: .main)

        dataSource.apply(snapshot, animatingDifferences: true)

    }

    

    @objc func insertData() {

        let color = UIColor(red: CGFloat.random(in: 0 ..< 1), green: CGFloat.random(in: 0 ..< 1), blue: CGFloat.random(in: 0 ..< 1), alpha: 1)

        

        mainModels.append(contentsOf: [

            MyModel(title: "insert1", backgroundColor: color),

            MyModel(title: "insert2", backgroundColor: color),

            MyModel(title: "insert3", backgroundColor: color),

            MyModel(title: "insert4", backgroundColor: color),

            MyModel(title: "insert5", backgroundColor: color),

            MyModel(title: "insert6", backgroundColor: color),

            MyModel(title: "insert7", backgroundColor: color),

            MyModel(title: "insert8", backgroundColor: color)

        ])

        

        

        applySnapshot()

        

        UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseInOut, animations: {

            self.collectionHeight.constant = 350

            self.view.layoutIfNeeded()

        }, completion: nil)

  


    }

    

    @objc func deleteData() {

        if mainModels.count > 8 {

            mainModels.removeLast(8)

            applySnapshot()

            

            UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseInOut, animations: {

                self.collectionHeight.constant = 170

                self.view.layoutIfNeeded()

            }, completion: nil)

  


        }

    }

    

}

extension DiffableCollectionViewController: UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        mainModels.remove(at: indexPath.row)

        applySnapshot()

    }

}

Model

import Foundation

import UIKit

// 枚举默认就是Hashable类型

enum Section: CaseIterable {

    case main

}

  


// 自定义类型需要遵从Hashable协议

struct MyModel: Hashable {

    

    static let defaultColor = UIColor(red: CGFloat.random(in: 0 ..< 1), green: CGFloat.random(in: 0 ..< 1), blue: CGFloat.random(in: 0 ..< 1), alpha: 1)

    var title: String

    var backgroundColor: UIColor

  


    init(title: String, backgroundColor: UIColor = MyModel.defaultColor) {

        self.title = title

        self.backgroundColor = backgroundColor

        self.identifier = UUID()

    }

  


    private let identifier: UUID

  


    func hash(into hasher: inout Hasher) {

        hasher.combine(self.identifier)

    }

}