在 SwiftUI 中,生命周期管理是一项重要功能,开发者需要在某个视图的特定阶段执行代码逻辑,例如当视图出现、消失、弹出回到页面时响应事件。除了 onAppear
和 onDisappear
之外,SwiftUI 提供了一些其他的生命周期管理相关修饰符和工具。
以下是与生命周期相关的函数或修饰符的完整清单及其使用场景:
1. onAppear
#
- 描述:
当视图 第一次 出现在屏幕上时触发一次,并且每次重新进入页面时也会调用。 - 使用场景:
初始化一个视图时加载数据、开始网络请求、设置计时器等。
示例: #
struct OnAppearExampleView: View {
var body: some View {
Text("Hello, SwiftUI!")
.onAppear {
print("View has appeared!")
}
}
}
2. onDisappear
#
- 描述:
当视图即将从屏幕中 消失(或被销毁)时触发。 - 使用场景:
清理资源、取消任务、销毁计时器或停止某些活动。
示例: #
struct OnDisappearExampleView: View {
var body: some View {
Text("Goodbye, SwiftUI!")
.onDisappear {
print("View is about to disappear!")
}
}
}
3. task
#
- 描述:
在指定上下文中运行异步任务,通常在视图 首次出现 时触发。适用于需要异步操作的场景,比如数据加载。 - 使用场景:
异步的初始化任务,如通过网络请求加载数据。
示例: #
struct TaskExampleView: View {
var body: some View {
VStack {
Text("Loading...")
}
.task {
await fetchData() // 异步数据加载
}
}
func fetchData() async {
print("Fetching data...")
try? await Task.sleep(for: .seconds(2)) // 模拟网络加载
print("Data fetched!")
}
}
4. onChange(of:)
#
- 描述:
监听某个数据的状态变化。当绑定值发生更改时触发。 - 使用场景:
响应状态或变量的实时变化,比如监控表单输入更新、设置动画、操作应用逻辑。
示例: #
struct OnChangeExampleView: View {
@State private var name: String = ""
var body: some View {
TextField("Enter your name", text: $name)
.onChange(of: name) { newValue in
print("Name changed to: \(newValue)")
}
}
}
注意: #
onChange(of:)
是值变化监听器,不是视图生命周期事件管理器,尽管它可以很灵活地在状态变化时触发逻辑。
5. ScenePhase
生命周期监控
#
- 描述:
使用@Environment(\.scenePhase)
环境变量监控应用程序的生命周期状态(后台、活跃或非活跃状态)。 - 使用场景:
管理应用状态,比如在后台保存数据、暂停任务或激活任务。
三种状态值: #
active
: 应用处于前台并活动。inactive
: 应用处于前台但不是活动状态(如接收到来电时)。background
: 应用已进入后台。
示例: #
import SwiftUI
struct ScenePhaseExample: View {
@Environment(\.scenePhase) private var scenePhase
var body: some View {
Text("App Lifecycle Example")
.onChange(of: scenePhase) { newPhase in
switch newPhase {
case .active:
print("App is active")
case .inactive:
print("App is inactive")
case .background:
print("App is in background")
default:
break
}
}
}
}
6. onReceive
#
- 描述:
监听Publisher
的事件(例如Timer
或其他 Combine 流),当 Publisher 发送数据时触发。 - 使用场景:
适合倒计时、网络状态变化、外部事件变化等。
示例: #
struct OnReceiveExampleView: View {
@State private var currentTime = Date()
let timer = Timer.publish(every: 1.0, on: .main, in: .common).autoconnect()
var body: some View {
Text("Current Time: \(currentTime)")
.onReceive(timer) { time in
currentTime = time // 更新时间
}
}
}
7. Environment
定制视图环境(类似生命周期)
#
- 描述:
通过@Environment
和@EnvironmentObject
管理一些全局环境值的切换,例如监控竖屏与横屏的切换、暗黑模式等。 - 使用场景:
检测系统环境(如通知设置、配色主题)或自定义共享的数据环境。
示例:检测屏幕方向 #
struct OrientationExampleView: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass
var body: some View {
Text(horizontalSizeClass == .compact ? "Portrait" : "Landscape")
.onAppear {
print("View loaded in \(horizontalSizeClass == .compact ? "Portrait" : "Landscape")")
}
}
}
8. Custom Task Cancellation (自定义任务管理) #
SwiftUI 中 Task
的生命周期会跟随视图销毁。如果需要手动控制任务取消(例如处理某些长时间运行的任务),可以使用 Task.handle
示例: #
struct LongOperationExample: View {
@State private var counter = 0
@State private var task: Task<Void, Never>? = nil
var body: some View {
VStack {
Text("Counter: \(counter)")
Button("Start Counting") {
task = Task {
while !Task.isCancelled {
try? await Task.sleep(for: .seconds(1))
counter += 1
}
}
}
Button("Stop Counting") {
task?.cancel() // 手动取消任务
}
}
}
}
总结对比 #
触发器 | 描述 | 应用场景 |
---|---|---|
onAppear | 当视图首次出现在屏幕上 | 初始化数据、加载任务 |
onDisappear | 当视图从屏幕上消失 | 停止计时器、清理资源 |
task | 在 onAppear 时运行异步任务(更适合异步代码) | 执行异步操作,如网络加载 |
onChange(of:) | 监听某个值的变化 | 动态响应绑定值的更新 |
scenePhase | 监听应用级别的生命周期变化,例如 active , background 和 inactive 状态 | 应用状态管理(保存、恢复任务等) |
onReceive | 监听 Combine 发布者(Publisher),如 Timer 和通知流 | 定时任务、外部事件处理 |
Environment 或 Dynamic | 使用环境值来检测系统(如屏幕方向、配色模式) | 根据环境自适应视图显示 |
取消任务(Task ) | 手动取消正在运行的长期任务 | 精细控制长时间任务的终止 |
以下是与 SwiftUI 生命周期管理相关的函数的官方 Apple 文档链接: #
1. onReceive #
- onReceive(_:perform:) 官方文档
onReceive
用于当视图检测到Publisher
数据时触发。
2. onAppear #
- onAppear(perform:) 官方文档
onAppear
可触发视图刚刚显示时的操作。
3. onDisappear #
- onDisappear(perform:) 官方文档
onDisappear
在视图即将从屏幕上消失时被触发。
4. onChange(of:) #
- onChange(of:perform:) 官方文档
用于监听指定值的变化,并触发相关操作。
5. ScenePhase 监控 #
- ScenePhase 官方文档
用于监控应用场景的生命周期状态(如活跃、后台等)。
6. task #
- task(priority:_:) 官方文档
task
在视图出现时启动一个异步任务,或者根据 ID 动态重新启动任务。