SwiftUI vs UIKit 2026:选哪个、怎么混用不踩坑
上个季度我用 SwiftUI 两天搭完一个设置页,爽得差点以为以后再也不碰 UIKit 了。结果下一个迭代要做一个可重排、带多分区粘性头的列表,我硬扛了三天,最后还是乖乖 UIViewControllerRepresentable 包了个 UICollectionView 兜底。这种"前半截飞快、后半截撞墙"的体验,我这几年踩了不止一次。
所以"2026 还该不该用 SwiftUI"——框架早就准备好了,真正的问题是你做的是什么页面。下面是我自己各发版踩下来的看法,不是文档复述。
SwiftUI 在 2026 的状态
2019 年坎坷上线后的重大进步:
- 性能 — iOS 17+ 上 SwiftUI 真的快了,新渲染器 + @Observable 替代 ObservableObject。
- 导航 —
NavigationStack终于提供了不和框架打架的程序化导航。 - 列表虚拟化 —
LazyVStack/List现在真正虚拟化。 - 自定义布局 —
Layout协议解锁了过去必须 UIKit 才能做的事。
仍然粗糙的地方:
- 复杂 collection view(重排、多分区粘性头)UIKit 仍然更顺手。
- 地图/视频/摄像头集成多半还要
UIViewRepresentable。 - 超出
matchedGeometryEffect的自定义转场仍受限。
懒得往下读的话,先看这张我自己常用的速查表:
| 维度 | SwiftUI | UIKit |
|---|---|---|
| 适用场景 | 表单/列表/设置/详情、多端共用、数据驱动布局 | 复杂 collection view、相机/AVFoundation、老 app 维护 |
| 开发速度 | 快,简单页面能省一半时间 | 慢,但复杂交互更可控 |
| 主要踩坑 | 大列表性能悬崖、自定义转场受限、状态调试反直觉 | 样板代码多、布局手写心智负担大 |
| 混用建议 | 用 UIHostingController 当叶子页 | 用 UIViewControllerRepresentable 兜底硬骨头 |
什么时候用 SwiftUI 起新页面
- 表单、列表、设置页、详情页 → SwiftUI。
- 数据驱动的动态布局 → SwiftUI(@Observable + body 模型很合适)。
- 要同时跑 iPad、Mac Catalyst、visionOS → SwiftUI。
什么时候伸手去拿 UIKit
- 重度
UICollectionViewCompositionalLayout+ 自定义补充视图。 - 深度 AVFoundation 集成 + 自定义预览 UI。
- 老 app 里有数千行
UIViewController,扩展比重写省事。 - 需要 SwiftUI 还没暴露的精准手势/触摸处理。
怎么把两者混好
边界是 UIHostingController(UIKit 装 SwiftUI)和 UIViewControllerRepresentable(SwiftUI 装 UIKit)。两条规则:
1. 在 controller 层级跨边界,不在 view 层级
// 好 —— 包整个屏幕
let host = UIHostingController(rootView: SettingsView())
navigationController.pushViewController(host, animated: true)
// 危险 —— 把一小段 SwiftUI 嵌进 UIKit cell
// 会引发生命周期与尺寸问题,避免。
2. 不要直接共享可变状态跨边界
传不可变快照进去,事件通过回调或 Combine 发出来。把 @ObservableObject 实例同时塞两边理论可行,实操会出引用 bug。
struct SettingsView: View {
let initialPrefs: Prefs
let onSave: (Prefs) -> Void
}
导航 — 最棘手的话题
2026 年的答案:
- 新 app →
NavigationStack+Path用[any Hashable]或自定义 enum。 - 已有 UIKit app → 保留
UINavigationController,叶子页面用UIHostingController包。 - 混合 → 用 UIKit 导航做底盘,SwiftUI 页面是乘客。
会让人翻车的模式:让 SwiftUI NavigationStack 和 UINavigationController 平级并存。选一个做底盘。
性能现实检查
90% 的页面 SwiftUI 已经够快,你测不出差别。剩下 10%:
- 长滚动列表 + 复杂 cell → 先测。SwiftUI 的
List已有竞争力,真测到掉帧再回到UICollectionView。 - 实时绘制(图表、自定义画布)→
Canvas够好,但最难的场景CADisplayLink+ Metal 仍胜。 - 动画密集的引导流 → SwiftUI 实际更好;声明式动画模型很强。
实际选型
- 新 C 端 iOS app → SwiftUI 上下通吃。第三方组件强制时才
UIViewRepresentable。 - iPad / Mac / visionOS → 必须 SwiftUI。
- 内嵌进别人 app 的 SDK → UIKit,因为你不知道宿主 app 的 iOS 部署版本。
- 银行 8 年 UIKit 老 app → 不重写。新页面用 SwiftUI + hosting controller 即可。
反模式
- "为学 SwiftUI" 重写跑得好的 UIKit app。 业余项目学,别赌一个季度。
- 5 屏 SwiftUI app 上自定义 Coordinator 模式。 用
NavigationStack,Coordinator 是 UIKit 时代的补丁。 - 强行让 SwiftUI 兼容 iOS 14。 能跑,但 API 缺口太大。如果能放弃 iOS 14 就放弃。
- "团队会 ObservableObject" 就不用 @Observable。 macro 显著更清爽,迁移机械化。
一句话总结
- 2026 新代码默认 SwiftUI。
- UIKit 仍适合:老代码维护、深度 AVFoundation、特定 UICollectionView 场景。
- 在 controller 边界混,不在 view 边界混。
- 导航选一个底盘。
- 不要"为干净"重写跑得好的 UIKit 代码——那从来不是真正的 ROI。
我们是一支开发者小团队,负责构建和维护 ToolsForge —— 150+ 个完全在浏览器本地运行、隐私优先的工具。这些文章来自我们日常的工程实践,而不是纸上谈兵。
了解我们相关阅读
一张照片能做多少事:AI 改图工具实战指南
换发型、换发色、换装、转卡通、风格迁移、室内设计、老照片修复——用一张照片走完这些 AI 改图流程,以及怎么让结果更稳、更像本人。
把脸保住:AI 改图提示词怎么写才不"换人"
换发型、换装、换风格时,AI 老把脸也改了?这篇讲清楚改图提示词的写法:保人约束、双通道(gpt-image-2 / Nano Banana)各自的脾气,以及一套能直接抄的模板。
TypeScript 类型体操:什么时候值,什么时候在炫技
务实的 TypeScript 高级类型指南 — mapped types、conditional types、template literal types 真正能给你什么,什么时候用,什么时候应该退回到朴素代码。