🧩 iOS UICollectionViewDiffableDataSource 使用指南(实战版)
适用于:UIKit 项目 / UICollectionView 目标:用最少代码实现稳定、可维护、带动画的数据更新
✨ 一、为什么要用 Diffable?
传统方式:
performBatchUpdates {
insertItems / deleteItems
}
问题:
- ❌ 容易崩溃(indexPath 不一致)
- ❌ 代码复杂
- ❌ 和自定义 layout 动画冲突
✅ Diffable 核心思想
👉 用“数据快照(Snapshot)”驱动 UI
🧠 二、步骤总览
1️⃣ 定义 Section 2️⃣ 定义 Item(必须 Hashable) 3️⃣ 创建 DataSource 4️⃣ 构建 Snapshot 5️⃣ 应用 Snapshot
🧩 三、定义数据模型
enum Section: Hashable {
case main
}
struct ImageItem: Hashable {
let id: UUID
let name: String
}
🏗 四、创建 DataSource
var dataSource: UICollectionViewDiffableDataSource<Section, ImageItem>!
dataSource = UICollectionViewDiffableDataSource(
collectionView: collectionView
) { collectionView, indexPath, item in
let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: "ImageCell",
for: indexPath
) as! ImageCell
cell.imageView.image = UIImage(named: item.name)
return cell
}
🔥 五、创建并应用 Snapshot
func applySnapshot(animated: Bool = true) {
var snapshot = NSDiffableDataSourceSnapshot<Section, ImageItem>()
snapshot.appendSections([.main])
snapshot.appendItems(items, toSection: .main)
dataSource.apply(snapshot, animatingDifferences: animated)
}
➕ 六、添加数据
func addItem() {
let item = ImageItem(id: UUID(), name: "image_1")
items.append(item)
applySnapshot()
}
➖ 七、删除数据
func deleteItem(at indexPath: IndexPath) {
let item = items[indexPath.item]
items.removeAll { $0.id == item.id }
applySnapshot()
}
🎬 八、动画说明
applySnapshot()
自动获得:
- 插入动画
- 删除动画
- 移动动画
⚠️ 九、重要注意事项
❌ 不要再使用:
performBatchUpdates
❌ 不要手动操作 indexPath
❌ 不要同时做:
更新数据 + 切换 layout
✅ 正确顺序
applySnapshot()
DispatchQueue.main.async {
collectionView.setCollectionViewLayout(layout, animated: true)
}
🚀 十、总结
👉 DiffableDataSource = 更安全的数据驱动 UI 👉 不再关心 indexPath 👉 自动动画
🎯 推荐使用场景
- 拼图 App
- 图片列表
- 聊天列表
- 商品列表
如果你觉得有用,欢迎点赞 👍