Highlight
这是一场面向 SwiftUI 入门到中级开发者的基础梳理 Session。讲者用一个「宠物 trick 排行榜」app 作为贯穿始终的示例,从最基础的 View 概念讲到 List、Navigation、自定义组件、状态管理,最后到和其他框架的集成。
核心内容
这是一场面向 SwiftUI 入门到中级开发者的基础梳理 Session。讲者用一个「宠物 trick 排行榜」app 作为贯穿始终的示例,从最基础的 View 概念讲到 List、Navigation、自定义组件、状态管理,最后到和其他框架的集成。
核心内容分三个层面。第一层是 View 的本质:SwiftUI 的 View 是声明式的描述,不是长期存在的对象实例。每次状态变化时,SwiftUI 会重新求值 View body,生成新的描述,然后高效地更新渲染。第二层是组合:通过容器视图(HStack、VStack、List)和 View Modifier 把简单视图组合成复杂界面。第三层是状态驱动:用 @State、@Bindable、@Environment 等属性包装器声明数据依赖,SwiftUI 自动处理 UI 更新(00:07)。
Session 还花了不少篇幅讲 SwiftUI 如何与其他框架共存——UIKit 互操作、SwiftData 持久化、Widget 扩展——强调 SwiftUI 天生支持增量采用,不需要整个 app 重写(21:08)。
详细内容
声明式 View 的本质
SwiftUI 的 View 是值类型(struct),不是长期存在的对象实例。每次状态变化时,SwiftUI 会重新求值 View body,生成新的描述,然后高效地更新渲染。这意味着你不需要手动管理视图生命周期,只需描述「UI 应该是什么样子」(00:09)。
// 基础 View 声明
HStack {
Label("Pet Tricks", systemImage: "pawprint")
Spacer()
Text("Rank")
}
关键点:
HStack是容器视图,水平排列子视图Label组合图标和文本,是 SwiftUI 内置的组合控件Spacer自动占据剩余空间,实现布局对齐
List 和 ForEach 的组合
List 是最常用的容器视图之一。它接受一个集合参数,内部自动创建 ForEach 视图为每个元素生成行。这意味着你不需要手动管理复用和滚动性能(02:56)。
// List 自动为集合中每个元素创建行
List(pets) { pet in
HStack {
Text(pet.name)
Text(pet.trick)
}
}
关键点:
List的集合参数自动创建ForEach视图- 每个元素对应一个
HStack行视图 - SwiftUI 自动处理滚动性能和视图复用
View Modifier 的链式调用
View Modifier 是 SwiftUI 的另一个核心模式。它是对基础视图的「修饰」,返回一个新的修饰后的视图。多个 Modifier 可以链式调用,形成清晰的效果层次(06:17)。
// View Modifier 链式调用
Image("whiskers")
.clipShape(Circle())
.shadow(radius: 5)
.overlay(Circle().stroke(Color.green, lineWidth: 2))
关键点:
clipShape(Circle())将图片裁剪为圆形shadow(radius:)添加阴影效果overlay在上方叠加绿色边框- Modifier 的顺序决定效果的应用顺序
自定义 View 的封装
当界面变复杂时,可以把视图层级封装成自定义 View。自定义 View 只需遵循 View 协议,提供 body 属性即可。因为 View 是值类型,拆分视图不会损害性能(07:02)。
// 自定义 View 封装
struct PetRow: View {
let pet: Pet
var body: some View {
HStack {
ProfileImage(for: pet)
VStack(alignment: .leading) {
Text(pet.name)
Text(pet.trick)
}
}
}
private var profileImage: some View {
Image(pet.imageName)
.clipShape(Circle())
.shadow(radius: 5)
}
}
关键点:
- 自定义 View 可以添加属性作为输入参数
private计算属性帮助组织代码- View 可以在任何需要的地方复用,如
List(pets) { PetRow(pet: $0) }
状态驱动的 UI 更新
SwiftUI 的第三个核心特性是状态驱动。当状态变化时,SwiftUI 自动重新计算依赖该状态的 View body,更新 UI。这消除了手动更新 UI 的样板代码和更新遗漏 bug(08:50)。
// 状态驱动的条件渲染
struct PetRow: View {
let pet: ObservablePet
var body: some View {
HStack {
Text(pet.name)
if pet.hasAward {
Image(systemName: "trophy.fill")
}
}
}
}
关键点:
pet.hasAward变化时,SwiftUI 自动重新计算body- 条件渲染自动更新,无需手动刷新
- SwiftUI 追踪 View body 中使用的属性,建立依赖关系
@State 和 Binding
@State 创建 View 的内部状态源。Binding 是对其他 View 状态的双向引用。通过 Binding,子 View 可以修改父 View 的状态,实现状态共享(09:30)。
// @State 创建内部状态
struct RatingView: View {
@State private var rating = 0
var body: some View {
HStack {
Button("-") { rating -= 1 }
Text("\(rating)")
Button("+") { rating += 1 }
}
}
}
// Binding 共享状态
struct RatingContainer: View {
@State private var rating = 0
var body: some View {
VStack {
Gauge(value: rating, in: 0...10)
RatingView(rating: $rating) // 传递 Binding
}
}
}
struct RatingView: View {
@Binding var rating: Int // 接收 Binding
var body: some View {
HStack {
Button("-") { rating -= 1 }
Text("\(rating)")
Button("+") { rating += 1 }
}
}
}
关键点:
@State让 SwiftUI 管理属性存储$前缀创建 Binding,实现双向绑定- 子 View 修改 Binding 会更新父 View 状态
- 状态共享让多个 View 同步更新
动画集成
SwiftUI 的动画构建在状态驱动的更新机制上。用 withAnimation 包裹状态变化,SwiftUI 会自动应用默认动画。也可以自定义动画曲线和过渡效果(11:40)。
// 状态驱动的动画
Button("+") {
withAnimation {
rating += 1
}
}
// 自定义过渡效果
Text("\(rating)")
.contentTransition(.numericText())
关键点:
withAnimation包装状态变化,触发动画.numericText()过渡适合数字变化- 动画是声明式的,无需手动控制时序
自适应控件
SwiftUI 的控件是「目的描述」而非精确视觉构造。Button 只声明「带标签的动作」,具体样式会根据上下文自动适配——在列表中是滑动操作,在菜单中是菜单项(14:09)。
// 自适应搜索
List(pets) { pet in
PetRow(pet: pet)
}
.searchable(text: $searchText)
关键点:
.searchablemodifier 自动添加搜索功能- iOS 显示覆盖列表,macOS 显示下拉菜单
- 控件根据上下文自动适配样式
平台适配与互操作
SwiftUI 支持所有 Apple 平台。同一套代码可以自动适配不同平台的设计规范——macOS 支持多窗口,watchOS 支持数码表冠滚动,visionOS 支持空间内容(15:54)。
// watchOS 数码表冠滚动
.scoreboard
.digitalCrownRotation($rating, from: 0, through: 10)
// UIKit 互操作
struct UIKitView: UIViewRepresentable {
func makeUIView(context: Context) -> UIViewType {
// 创建 UIKit 视图
}
func updateUIView(_ uiView: UIViewType, context: Context) {
// 更新 UIKit 视图
}
}
关键点:
.digitalCrownRotation启用数码表冠控制UIViewRepresentable在 SwiftUI 中嵌入 UIKit 视图UIHostingController在 UIKit 中嵌入 SwiftUI 视图
核心启发
-
从 UIKit 迁移:不要试图一次性重写。SwiftUI 的
UIViewRepresentable和UIHostingController让你可以在 UIKit 中嵌入单个 SwiftUI 视图,或反过来。找到一个独立的、边界清晰的 feature(比如设置页面、新手引导),先用 SwiftUI 实现它,验证团队的学习曲线和开发效率。 -
新项目直接用 SwiftUI。Apple 内部已经在大量新 app 中使用 SwiftUI,框架的成熟度已经不是问题。搭配 SwiftData 做数据持久化,用
@Query自动同步 UI 和数据,整个技术栈都是声明式的。但要注意一些高级自定义场景可能还是需要回退到 UIKit,比如高度自定义的滚动行为、复杂的触摸事件处理。 -
善用 View 的值类型特性拆分代码。把大 View 拆成小 View,每个 View 接受明确的输入参数。不要在一个 View 的 body 里写 200 行代码——拆成 5 个子 View 不仅更易维护,对性能也没有负面影响。SwiftUI 会高效地更新只依赖变化状态的那些 View。
关联 Session
- What’s new in SwiftUI — 深入讲解 SwiftUI 2024 的新特性,包括新的 API 和改进
- Bring SwiftData to your SwiftUI app — 如何在 SwiftUI 中集成 SwiftData 持久化
- SwiftUI for watchOS — 针对 Apple Watch 的 SwiftUI 开发实践
- Advances in SwiftUI Animation — SwiftUI 动画系统的高级用法
- Build SwiftUI apps for visionOS — 为 visionOS 构建 SwiftUI 空间计算应用
评论
GitHub Issues · utterances