UICollectionView 和 UITableView 新旧 API对比

在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 模式
  • 三分离协议:UICollectionViewDataSourceUICollectionViewDelegateUICollectionViewDelegateFlowLayout
  • 布局系统相对固定(主要是 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
    // 返回配置好的补充视图
}

六、性能优化对比

传统性能考虑

  1. Cell 复用标识符管理
  2. 手动计算和缓存行高
  3. 复杂的布局计算逻辑
  4. 需要手动处理数据变化时的动画

现代优化特性

  1. 自动差异化计算:Diffable DataSource 自动计算数据变化
  2. 内置性能优化:Compositional Layout 自动优化布局计算
  3. 更高效的 Cell 准备:Content Configuration 系统减少配置开销
  4. 智能预取:改进的预取机制与 Diffable DataSource 协同工作

现代 API 代表了 Apple 在 UI 开发方向上的未来趋势,虽然学习成本较高,但能显著提高开发效率和代码质量,特别适合复杂界面和数据频繁变化的场景。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容