Use SwiftUI with UIKit
Swift & UI 进阶 20m

在 UIKit 中使用 SwiftUI

Use SwiftUI with UIKit

2022年6月6日

在 Apple 官方观看视频

一句话判断

UIHostingController 的增强、SwiftUI 视图用作 UICollectionView/UITableView cell——这场 Session 是渐进式 SwiftUI 采用的实操指南。

这场 Session 讲了什么

Health 应用团队的 Sara Frederixon 以亲身经验讲解了如何在现有 UIKit 应用中逐步引入 SwiftUI。Session 覆盖了四个方面:UIHostingController 的更新、SwiftUI 视图与现有数据源的对接、用 SwiftUI 构建 Collection View 和 Table View cell、以及混合使用时的数据流管理。

核心观点是:不需要重写整个应用,可以从一个视图、一个 cell 开始逐步采用 SwiftUI。

值得深挖的点

UIHostingController 的灵活性。可以在任何能用 UIViewController 的地方使用 UIHostingController:push、present、嵌入 container view。今年的更新增加了更多配置选项,让 SwiftUI 视图更好地融入 UIKit 导航体系。

SwiftUI Cell in UICollectionView/UITableView。今年最重要的新能力:可以用 SwiftUI 视图直接作为 collection view 和 table view 的 cell。这意味着复杂的数据可视化 cell 可以用 SwiftUI 编写,同时保持 UIKit 的性能优势。

数据流的双向桥接。UIKit 应用通常有成熟的数据层(如 Core Data、DataSource)。SwiftUI 视图需要响应数据变化,关键是用 @ObservedObject 或 @EnvironmentObject 将现有的 Observable 对象桥接到 SwiftUI 视图中。

Hosting Configuration 模式。新的 UIHostingConfiguration 允许你为 cell 创建 SwiftUI 视图,同时保留 UIKit 的回滚复用(dequeue/reuse)机制。

代码片段

// 用 SwiftUI 视图作为 UICollectionView Cell
let registration = UICollectionView.CellRegistration<CollectionViewCell, Item> { cell, indexPath, item in
    cell.contentConfiguration = UIHostingConfiguration {
        // SwiftUI 视图作为 cell 内容
        HeartRateView(heartRate: item.heartRate, date: item.date)
    }
}

// UIHostingController 嵌入到 UIKit 导航
let hostingController = UIHostingController(rootView: HeartRateView())
navigationController?.pushViewController(hostingController, animated: true)

// 桥接 Observable 数据
class HealthDataStore: ObservableObject {
    @Published var heartRates: [HeartRate] = []
}

struct HeartRateView: View {
    @ObservedObject var store: HealthDataStore
    var body: some View {
        List(store.heartRates) { rate in
            Text("\(rate.bpm) BPM")
        }
    }
}

最佳实践

  • 从独立的页面或 cell 开始引入 SwiftUI,不要试图一次性迁移整个模块
  • UIHostingConfiguration 配合 cell reuse 机制使用,性能表现接近原生 UIKit cell
  • 数据层保持不变,通过 ObservableObject 桥接到 SwiftUI
  • 复杂的自定义 cell 是 SwiftUI 的最佳切入点——SwiftUI 的声明式语法让复杂布局更易维护
  • 注意 SwiftUI 视图在 UIKit 中的布局约束传递,用 hostingController.sizingOptions 控制尺寸行为

还有什么值得关注

  • UIKit 和 SwiftUI 的互操作是双向的——也可以在 SwiftUI 中嵌入 UIKit 视图
  • Collection view 的 diffable data source 与 SwiftUI 视图配合使用效果很好
  • 性能关键场景(如滚动大量 cell)需要评估 SwiftUI 视图的渲染开销
  • 参考 “Bring SwiftUI to your UIKit apps” Session 获取更多互操作细节
WWDC 2022