在iOS开发中,UICollectionView 和 UITableView 是两个非常重要的UI组件,用于展示数据集合。随着时间的发展,Apple对这两个组件进行了多次更新和优化,引入了新API来提升性能、简化代码以及提供更多的功能。
下面我将从多个维度对这两个核心列表视图的新旧 API 进行详细对比分析,包括架构设计、数据管理、UI 配置、性能优化等方面的变化。(旧版本:Objective-C时代及早期Swift,iOS13之前)
一、架构设计对比
UITableView
传统架构 (iOS 13 之前,Objective-C时代及早期Swift):
- 基于 MVC 设计模式
- 数据源和委托分离 (
UITableViewDataSource
&UITableViewDelegate
) - 需要手动管理数据与界面的同步
- 高度依赖 IndexPath 进行数据定位
现代架构 (iOS 14+):
- 采用声明式编程范式
- 引入
UITableViewDiffableDataSource
统一管理数据 - 自动处理数据与界面的同步
- 基于 Section/Item 标识符的数据模型
- 支持快照(Snapshot)更新机制
UICollectionView
传统架构 (iOS 13 之前,Objective-C时代及早期Swift):
- 同样基于 MVC 模式
- 三分离协议:
UICollectionViewDataSource
、UICollectionViewDelegate
、UICollectionViewDelegateFlowLayout
- 布局系统相对固定(主要是 FlowLayout)
- 需要手动计算和更新布局
现代架构 (iOS 14+):
- 组合式架构设计
- 引入
UICollectionViewDiffableDataSource
- 强大的
UICollectionViewCompositionalLayout
系统 - 支持列表、网格、自定义布局的统一配置
- 内置补充视图(Supplementary Views)支持
二、数据管理对比
数据源实现
传统方式:
// UITableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = data[indexPath.row].title
return cell
}
// UICollectionView
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
// 配置 cell
return cell
}
现代方式:
// UITableView
let dataSource = UITableViewDiffableDataSource<Section, Item>(tableView: tableView) {
tableView, indexPath, item in
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
var content = cell.defaultContentConfiguration()
content.text = item.title
cell.contentConfiguration = content
return cell
}
// UICollectionView
let dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) {
collectionView, indexPath, item in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
// 使用 content configuration 配置 cell
return cell
}
数据更新机制
传统方式:
// 局部刷新
tableView.reloadRows(at: [indexPath], with: .automatic)
collectionView.reloadItems(at: [indexPath])
// 全部刷新
tableView.reloadData()
collectionView.reloadData()
现代方式:
// 创建快照
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.main])
snapshot.appendItems(items)
// 应用快照
dataSource.apply(snapshot, animatingDifferences: true)
三、UI 配置系统对比
Cell 内容配置
传统方式:
// UITableViewCell
cell.textLabel?.text = "Title"
cell.detailTextLabel?.text = "Subtitle"
cell.imageView?.image = UIImage(named: "icon")
// UICollectionViewCell
// 通常需要自定义子视图并手动布局
现代方式 (Content Configuration):
// 统一配置系统
var content = cell.defaultContentConfiguration()
content.text = "Title"
content.secondaryText = "Subtitle"
content.image = UIImage(systemName: "star")
content.imageProperties.tintColor = .systemBlue
cell.contentConfiguration = content
// 列表专用配置
var content = UIListContentConfiguration.cell()
content.text = "List Title"
content.secondaryTextProperties.numberOfLines = 2
cell.contentConfiguration = content
状态管理
传统方式:
// 需要重写多个方法处理不同状态
override func setSelected(_ selected: Bool, animated: Bool)
override func setHighlighted(_ highlighted: Bool, animated: Bool)
现代方式:
// 统一状态处理
override func updateConfiguration(using state: UICellConfigurationState) {
var content = UIListContentConfiguration.cell().updated(for: state)
if state.isHighlighted || state.isSelected {
content.textProperties.color = .white
content.background.backgroundColor = .systemBlue
} else {
content.textProperties.color = .label
content.background.backgroundColor = .systemBackground
}
self.contentConfiguration = content
}
四、布局系统对比 (UICollectionView)
传统布局系统
let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: 100, height: 100)
layout.minimumInteritemSpacing = 10
layout.minimumLineSpacing = 10
layout.scrollDirection = .vertical
layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
现代组合式布局系统
// 简单列表布局
let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
let layout = UICollectionViewCompositionalLayout.list(using: config)
// 复杂组合布局
let layout = UICollectionViewCompositionalLayout { sectionIndex, layoutEnvironment in
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5),
heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(100))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,
subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 10
section.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10)
return section
}
五、补充视图支持对比
传统方式
// 注册补充视图
collectionView.register(HeaderView.self,
forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
withReuseIdentifier: "header")
// 实现数据源方法
func collectionView(_ collectionView: UICollectionView,
viewForSupplementaryElementOfKind kind: String,
at indexPath: IndexPath) -> UICollectionReusableView {
// 手动配置补充视图
}
现代方式
// 使用 Compositional Layout 定义补充视图
let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .estimated(50))
let header = NSCollectionLayoutBoundarySupplementaryItem(
layoutSize: headerSize,
elementKind: UICollectionView.elementKindSectionHeader,
alignment: .top)
section.boundarySupplementaryItems = [header]
// 使用 Diffable DataSource 配置补充视图
dataSource.supplementaryViewProvider = { collectionView, kind, indexPath in
// 返回配置好的补充视图
}
六、性能优化对比
传统性能考虑
- Cell 复用标识符管理
- 手动计算和缓存行高
- 复杂的布局计算逻辑
- 需要手动处理数据变化时的动画
现代优化特性
- 自动差异化计算:Diffable DataSource 自动计算数据变化
- 内置性能优化:Compositional Layout 自动优化布局计算
- 更高效的 Cell 准备:Content Configuration 系统减少配置开销
- 智能预取:改进的预取机制与 Diffable DataSource 协同工作
现代 API 代表了 Apple 在 UI 开发方向上的未来趋势,虽然学习成本较高,但能显著提高开发效率和代码质量,特别适合复杂界面和数据频繁变化的场景。