什么是 SwiftUI
SwiftUI 是 Apple 于 2019 年推出的声明式 UI 框架,用 Swift 一门语言同时构建 iOS、macOS、watchOS、tvOS 的界面。和 UIKit 的命令式写法不同,SwiftUI 是”声明界面长什么样,状态变了界面自动更新”。
| UIKit |
SwiftUI |
| Storyboard/代码 + Auto Layout |
纯 Swift 声明式布局 |
| delegate/target-action 回调 |
闭包、@State 驱动 |
| 手动刷新 UI |
状态变化自动刷新 |
一、创建工程
打开 Xcode → File → New → Project → App,Interface 选 SwiftUI,Language 选 Swift。生成的核心文件是 AppNameApp.swift(App 入口)和 ContentView.swift(首页)。
入口文件:
1 2 3 4 5 6 7 8 9 10
| import SwiftUI
@main struct MyAppApp: App { var body: some Scene { WindowGroup { ContentView() } } }
|
二、第一个页面:布局与文本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import SwiftUI
struct ContentView: View { var body: some View { VStack(spacing: 16) { Text("Hello, SwiftUI!") .font(.largeTitle) .fontWeight(.bold)
Text("这是我用 SwiftUI 写的第一个页面") .font(.body) .foregroundColor(.secondary)
HStack(spacing: 12) { Text("左") Spacer() Text("右") } .padding() .background(Color.gray.opacity(0.1)) .cornerRadius(8) } .padding() } }
|
布局三件套:VStack(垂直)、HStack(水平)、ZStack(层叠)。修饰符(.font、.padding、.background)链式叠加,顺序影响效果。
三、状态管理:@State
SwiftUI 中用 @State 声明视图私有状态,状态改变视图自动刷新:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| struct CounterView: View { @State private var count = 0
var body: some View { VStack(spacing: 16) { Text("点击次数:\(count)") .font(.title)
Button(action: { count += 1 }) { Text("点我 +1") .padding() .background(Color.blue) .foregroundColor(.white) .cornerRadius(8) } } } }
|
@State 对应视图内部状态;跨视图共享用 @ObservedObject / @EnvironmentObject + ObservableObject(MVVM 中的 ViewModel)。
四、列表与导航
List 是 SwiftUI 的列表组件,配合 NavigationStack 实现页面跳转:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| struct Todo: Identifiable { let id = UUID() let title: String let done: Bool }
struct TodoListView: View { @State private var todos = [ Todo(title: "学习 SwiftUI", done: true), Todo(title: "写第一个 App", done: false), Todo(title: "上架 App Store", done: false) ]
var body: some View { NavigationStack { List($todos) { $todo in HStack { Image(systemName: todo.done ? "checkmark.circle.fill" : "circle") .foregroundColor(todo.done ? .green : .gray) .onTapGesture { todo.done.toggle() } Text(todo.title) .strikethrough(todo.done) } } .navigationTitle("待办清单") } } }
|
List($todos) 的 $ 是双向绑定(Binding),子元素可以直接修改父状态。navigationTitle 设置导航栏标题。
五、表单与输入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| struct LoginFormView: View { @State private var username = "" @State private var password = ""
var body: some View { Form { Section("账号") { TextField("用户名", text: $username) .textInputAutocapitalization(.never) SecureField("密码", text: $password) } Section { Button("登录") { } .disabled(username.isEmpty || password.isEmpty) } } } }
|
Form 自带分组和样式,SecureField 是密码输入框,.disabled 在条件不满足时禁用按钮。
六、@Preview 实时预览
Xcode 右侧的 Canvas 可以实时预览:
1 2 3
| #Preview { ContentView() }
|
支持深色模式预览:
1 2 3 4
| #Preview { ContentView() .preferredColorScheme(.dark) }
|
常见坑
- body 只能返回一个 View:需要多内容时用 Group 或 VStack 包起来;
- @State 只用于视图私有状态:跨界面共享数据要放 ObservableObject,否则数据不同步;
- 模拟器/真机跑不起来:优先检查 Xcode 版本与最低部署目标是否匹配;
- 预览不显示:很多时候是预览编译缓存问题,Product → Clean Build Folder 后重试。
总结
SwiftUI 的上手路径很顺:先掌握 VStack/HStack/ZStack 布局、@State 状态、List 列表,就能拼出大多数界面。下一步建议学 ObservableObject + @EnvironmentObject 的 MVVM 架构,以及 NavigationStack 的路径导航。