什么是 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)
}

常见坑

  1. body 只能返回一个 View:需要多内容时用 Group 或 VStack 包起来;
  2. @State 只用于视图私有状态:跨界面共享数据要放 ObservableObject,否则数据不同步;
  3. 模拟器/真机跑不起来:优先检查 Xcode 版本与最低部署目标是否匹配;
  4. 预览不显示:很多时候是预览编译缓存问题,Product → Clean Build Folder 后重试。

总结

SwiftUI 的上手路径很顺:先掌握 VStack/HStack/ZStack 布局、@State 状态、List 列表,就能拼出大多数界面。下一步建议学 ObservableObject + @EnvironmentObject 的 MVVM 架构,以及 NavigationStack 的路径导航。