很多 iOS 团队并不是不知道 SwiftUI 的方向,而是担心一次性重写成本太高、业务迭代被打断。对于已有 UIKit 项目,更现实的做法不是“全量翻新”,而是先判断哪些页面值得迁、哪些模块适合先动手,再利用 UIKit 与 SwiftUI 的互操作能力逐步替换。看完这篇,你可以建立一套更可执行的迁移顺序,也能判断哪些场景适合包装共存,哪些场景值得直接重写。
为什么 UIKit 项目还值得逐步迁移到 SwiftUI
自 2019 年苹果推出 SwiftUI 之后,iOS、macOS、watchOS 和 tvOS 的界面开发开始明显转向声明式模式。对新项目来说,SwiftUI 已经是绕不开的选择;对旧项目来说,问题往往不是要不要迁,而是何时开始、从哪里开始。
不少团队目前仍以 UIKit 为主,SwiftUI 只用于局部组件或新功能试点。核心原因通常不是技术不可行,而是迁移成本高、历史代码多、团队心智尚未完全切换。也正因为如此,渐进式迁移往往比一次性重构更适合真实业务环境。
迁移到 SwiftUI,能换来什么
1. 声明式语法更适合维护复杂 UI
SwiftUI 的核心优势之一,是开发者只需要描述界面应该如何呈现以及状态如何变化,框架会负责完成大量更新细节。相比 UIKit 中层层组装视图、手动同步状态的方式,这种写法通常更直观,代码量也更容易控制。
对于团队协作来说,这还意味着 UI 结构更清晰,可读性更高,后续维护时更容易定位问题。
2. 一套思路覆盖多个苹果平台
SwiftUI 从设计之初就面向所有苹果平台。对于需要在 iOS、macOS、watchOS 或 tvOS 间复用界面逻辑的团队,SwiftUI 能减少重复实现的成本,也更方便统一交互风格。
3. 实时预览能缩短迭代反馈周期
SwiftUI 提供了 Xcode 中的实时预览能力,界面调整后可以更快看到结果。对需要频繁打磨页面结构、状态切换和交互细节的场景来说,这种反馈速度会直接影响开发效率。
真正开始迁移前,先决定从哪里下手
评估现有代码库,先分清“适合迁”和“暂时别动”
迁移 UIKit 项目时,第一步不是写代码,而是先梳理现有 UI 资产。并不是所有页面、视图控制器或组件都必须立刻迁移到 SwiftUI,优先级应该结合以下几个维度来判断:

- 实现复杂度
- 使用频率
- 业务重要性
- 与其他模块的耦合程度
通常来说,独立性较高的小模块更适合作为起点,比如列表页、详情页、弹窗这类边界清晰的功能。先拿这些页面建立迁移经验,再逐步推进到更核心的业务区域,风险会低很多。
为什么“小步迁移”比“大重写”更现实
很多 UIKit 项目失败并不是因为 SwiftUI 不适合,而是因为一上来就试图整体替换。更可行的策略,是让迁移本身成为持续演进的一部分:先完成可独立上线的一小块,再验证稳定性、团队协作方式和开发效率,之后再扩大范围。
UIKit 和 SwiftUI 如何共存迁移
先把单个 UIKit 视图转换成 SwiftUI 视图
实际落地时,可以从单个视图开始迁移,而不是直接重写整套页面。这样做的好处是边界明确,回滚成本也低。

如果转换过程比较繁琐,也可以借助 ChatGPT、Cursor 之类的工具辅助生成初版代码,再由开发者结合项目结构进行校正和整理。对于重复性较强的 UI 改写,这类工具确实能提升效率。
当某些视图结构很复杂,暂时无法完整改写为 SwiftUI,但又需要和 SwiftUI 页面共存时,可以使用包装器接入 UIKit 视图。SwiftUI 提供了 UIViewRepresentable 和 UIViewControllerRepresentable 两类桥接能力。
import SwiftUI
struct MyUIKitView: UIViewRepresentable {
func makeUIView(context: Context) -> UIView {
let uiView = UIView()
// 在这里自定义你的 UIView
return uiView
}
func updateUIView(_ uiView: UIView, context: Context) {
// 如有需要,在这里更新你的 UIView
}
}
再逐步把视图控制器逻辑迁到 SwiftUI
当局部视图迁移顺利后,下一步可以考虑把视图控制器层的导航、布局和展示逻辑改写为 SwiftUI 风格。这里真正需要迁移的,不只是 UI 外观,还包括页面结构组织方式和状态驱动思路。
import SwiftUI
struct MySwiftUIView: View {
var body: some View {
NavigationView {
VStack {
Text("Hello, SwiftUI!")
}
.navigationTitle("Welcome")
}
}
}
原文中的 Na vigationView、.na vigationTitle 显然是排版导致的断裂写法,实际代码应为 NavigationView 和 .navigationTitle。
把 SwiftUI 页面嵌回现有 UIKit 工程
迁移并不总是“UIKit 包到 SwiftUI 里”,很多时候也需要反向集成,也就是把新的 SwiftUI 视图放回现有 UIKit 页面层级中。这时最常见的入口就是 UIHostingController。
import UIKit
import SwiftUI
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// 创建一个 SwiftUI 视图并将其添加到视图层次结构中
let swiftUIView = MySwiftUIView()
let hostingController = UIHostingController(rootView: swiftUIView)
addChild(hostingController)
view.addSubview(hostingController.view)
hostingController.didMove(toParent: self)
}
}
这类接入方式很适合在旧工程里逐步引入新页面,不必等待整个架构完全切换后再开始使用 SwiftUI。
迁移过程里最容易被忽略的两件事
1. 每一步都要测试,而不是最后统一验收
UIKit 到 SwiftUI 的迁移往往涉及页面结构、状态更新和导航方式的变化,改动范围看似局部,实际影响可能会扩散到交互链路。与其在末尾做一次集中验证,不如在每个模块迁移完成后就立即测试,尽早发现功能回归。

2. 迁的是代码,也是开发范式
除了具体实现,团队还需要接受 SwiftUI 的思路变化。UIKit 更偏命令式编程,而 SwiftUI 是声明式编程。如果只是把 UIKit 的写法“翻译”进 SwiftUI,通常会得到一套更复杂、可维护性更差的新代码。
更稳妥的做法包括:
- 从小组件、小页面开始,降低一次性风险。
- 充分利用 UIKit 与 SwiftUI 的互操作性,允许新旧代码长期共存。
- 用好实时预览和声明式状态更新,提高迭代效率。
- 在状态管理、动画和布局上尽量采用 SwiftUI 原生方式,而不是继续套用 UIKit 心智。
结语:UIKit 不必一夜下线,但团队该尽早进入 SwiftUI 节奏
从 UIKit 迁移到 SwiftUI,本质上不是一次简单的语法替换,而是 iOS 界面开发方式的一次持续演进。苹果近几年持续强化 SwiftUI 的位置,这个趋势已经很明确。
对于已有项目,与其纠结“什么时候全部迁完”,不如先建立一条可持续推进的路线:先评估、再试点、再共存、再扩展。这样既不会打断当前业务,也能让团队逐步积累 SwiftUI 的实际经验。
本文同步自微信公众号 “iOS新知”,每天准时分享一个新知识,这里只是同步。









