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