既然你已经有了 Swift 基础,学习 SwiftUI 会非常顺畅。SwiftUI 是一种 声明式 的 UI 框架,与你之前可能用过的 UIKit(命令式)在思维方式上有很大不同。
以下是基于你现有基础整理的 SwiftUI 快速上手指南:
2. SwiftUI 核心架构
View 协议
在 SwiftUI 中,所有东西都是 View。你的界面由一个个遵循 View 协议的结构体组成。
import SwiftUI
struct ContentView: View { // 1. 遵循 View 协议的结构体
var body: some View { // 2. 必须实现 computed property `body`
Text("Hello, World!") // 3. 返回一个 View
}
}
组合优于继承
UIKit 喜欢继承(例如继承 UIViewController),SwiftUI 喜欢组合。你把小的视图拼成大的视图。
struct UserInfoView: View {
var name: String
var body: some View {
HStack { // 水平排列
Image(systemName: "person.circle") // 系统图标
.font(.largeTitle)
VStack(alignment: .leading) { // 垂直排列
Text("用户名:")
.font(.caption)
Text(name)
.font(.title)
}
Spacer() // 弹性空间,把内容推到左边
}
.padding() // 添加内边距
.background(Color.gray.opacity(0.2)) // 背景色
.cornerRadius(10) // 圆角
}
}
3. 基础布局组件
用你熟悉的 Swift 语法来创建 UI:
VStack:垂直排列视图。HStack:水平排列视图。ZStack:重叠排列视图(类似于 UIKit 的addSubview,后添加的在上面)。List:类似 UITableView,用于展示滚动列表。NavigationStack:类似 UINavigationController,用于页面导航。Form:专门用来做设置页或输入页的表单。
4. 状态管理 (@State 和 @Binding)
这是 SwiftUI 的精华。既然你有 Swift 基础,可以把它理解为一种属性包装器,它让值类型(struct)拥有了类似引用的能力来触发 UI 刷新。
@State:用于视图内部的私有数据。当值改变时,body会自动刷新。@Binding:用于传递引用。一个视图持有数据源,另一个视图想读写这个数据但不拥有它。
举个计数器例子:
struct CounterView: View {
@State private var count = 0 // 数据源
var body: some View {
VStack {
Text("Count: \(count)")
.font(.largeTitle)
// 传递 $count (binding) 给子视图
CounterButton(count: $count)
}
}
}
struct CounterButton: View {
@Binding var count: Int // 我不拥有数据,我只是引用它
var body: some View {
Button("Increment") { // 按钮
count += 1 // 修改时,会通知 CounterView 刷新
}
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
5. 数据流进阶 (MVVM 模式)
除了 @State 用于局部,还有更强大的数据管理工具来处理复杂业务逻辑:
ObservableObject:这是一个协议,通常用于你的 ViewModel 类。@Published:属性包装器,标记 VM 中那些需要触发 UI 刷新的属性。@StateObject/@ObservedObject:在 View 中引用 VM 对象。@StateObject:View 持有该对象的生命周期(负责创建)。@ObservedObject:View 引用从外部传入的对象(不负责创建)。
// 2. View 结构体
struct UserProfileView: View {
@StateObject private var viewModel = UserViewModel() // 持有 VM
var body: some View {
VStack {
Text("Name: \(viewModel.username)")
Text("Age: \(viewModel.age)")
Button("Change Name") {
viewModel.updateName()
}
}
}
}
6. 布局与修饰符 (Modifiers)
在 SwiftUI 中,你通过修饰符来设置视图的属性(类似于 UIKit 中的 .property = value),链式调用非常优雅。
常用修饰符:
.padding():设置内边距。.foregroundColor():前景色(文字颜色/图标颜色)。.background():背景。.font():字体。.frame():设置宽高。.clipShape():裁剪形状(如圆角)。
7. 项目结构建议
一个典型的 SwiftUI 文件通常长这样:
import SwiftUI
// MARK: - Model (如果简单的话)
struct Item {
let name: String
}
// MARK: - ViewModel (如果需要的话)
class ItemListViewModel: ObservableObject {
@Published var items = [Item(name: "Apple"), Item(name: "Banana")]
}
// MARK: - View
struct ItemListView: View {
@StateObject private var viewModel = ItemListViewModel()
var body: some View {
NavigationStack {
List(viewModel.items, id: \.name) { item in // 遍历数据
ItemRowView(item: item)
}
.navigationTitle("Items")
}
}
}
struct ItemRowView: View {
let item: Item
var body: some View {
HStack {
Text(item.name)
Spacer()
Image(systemName: "info.circle")
}
.padding(.vertical, 4)
}
}
给你的学习建议
- 忘掉 Frame 和约束:SwiftUI 更多依赖于
Stack+Spacer+Padding来实现布局,而不是NSLayoutConstraint。 - 善用 Preview:SwiftUI 的 Canvas 预览非常好用。你可以一边写代码,一边实时看到 UI 变化。
- 遇到 UIKit 组件找不到时:SwiftUI 虽然强大,但有些 UIKit 的复杂组件暂时没有(比如
UICollectionView的高级布局)。这时候你需要用UIViewRepresentable来包装 UIKit 组件,这是另一个进阶话题。
有什么具体的 UI 或逻辑想用 SwiftUI 实现吗?