scenePhase 是 SwiftUI 中一个非常重要的环境值,用于检测和响应应用程序的生命周期状态(例如活跃、后台运行或暂停)。它与 @Environment 和 @EnvironmentObject 的使用密切相关,是管理应用状态变更的关键工具。
scenePhase 的定义
scenePhase 是一个 Environment 值,属于 EnvironmentValues 中的一个属性,类型为 ScenePhase。
它可以通过 @Environment(\.scenePhase) 获取,用来监听当前的场景阶段。
ScenePhase 的三种状态
ScenePhase 是一个枚举类型,包含以下三种主要状态:
1、active:场景处于活跃状态,应用当前在前台运行并接受用户输入。
2、inactive:场景处于非活跃状态,应用在前台但未接收用户输入(例如来电或显示锁屏时)。
3、background:场景已移到后台(应用未显示在用户视图中)。
基本用法
1、使用 @Environment 检测 scenePhase
通过将 @Environment(\.scenePhase) 注入到 SwiftUI 的 View 中,监听应用的生命周期变化:
import SwiftUI
struct ContentView: View {
@Environment(\.scenePhase) private var scenePhase
var body: some View {
Text("Hello, World!")
.padding()
.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
}
}
}
}
实际应用场景
1、保存数据到磁盘
在应用进入后台时保存数据,防止丢失:
.onChange(of: scenePhase) { newPhase in
if newPhase == .background {
saveDataToDisk()
}
}
2、暂停或恢复活动
暂停计时器或游戏活动:
.onChange(of: scenePhase) { newPhase in
if newPhase == .inactive {
pauseGame()
} else if newPhase == .active {
resumeGame()
}
}
3、记录用户使用时长
统计用户在应用处于活跃状态的时间:
@State private var startTime: Date?
.onChange(of: scenePhase) { newPhase in
if newPhase == .active {
startTime = Date()
} else if newPhase == .inactive || newPhase == .background {
if let startTime = startTime {
let usageDuration = Date().timeIntervalSince(startTime)
print("User used the app for \(usageDuration) seconds")
}
}
}
与 App 生命周期配合
在 SwiftUI 的 @main 应用入口中,可以通过 @Environment(\.scenePhase) 监控整个应用的状态变化。例如:
@main
struct MyApp: App {
@Environment(\.scenePhase) private var scenePhase
var body: some Scene {
WindowGroup {
ContentView()
}
.onChange(of: scenePhase) { newPhase in
switch newPhase {
case .active:
print("App is now active")
case .inactive:
print("App is now inactive")
case .background:
print("App is now in background")
@unknown default:
print("Unknown scene phase")
}
}
}
}
注意事项
1、针对多个场景(Scene):
如果应用支持多窗口,每个窗口会有自己的 scenePhase。
在这种情况下,最好为每个场景单独监听状态变化,而不是仅依赖全局的状态。
2、与 UIKit 的生命周期区别:
UIKit 中用 UIApplicationDelegate 和 UISceneDelegate 处理生命周期。
SwiftUI 更加简洁,直接使用 scenePhase 和 @Environment 配合即可。
3、注意后台模式的使用:
在 background 阶段执行任务时,如果需要长时间操作(如后台下载或保存大文件),需要在 Info.plist 中配置相应的后台权限。
总结
scenePhase 是 SwiftUI 提供的一种优雅方式,监控应用生命周期状态变化。它的响应式设计让开发者可以轻松地在视图层级中响应状态切换,无需复杂的代理或通知机制。
相关文章
1、从问题出发:研究环境变量scenePhase应用生命周期:https://fangjunyu.com/2024/10/15/%e4%bb%8e%e9%97%ae%e9%a2%98%e5%87%ba%e5%8f%91%ef%bc%9a%e7%a0%94%e7%a9%b6%e7%8e%af%e5%a2%83%e5%8f%98%e9%87%8fscenephase%e5%ba%94%e7%94%a8%e7%94%9f%e5%91%bd%e5%91%a8%e6%9c%9f/
2、iOS在后台阶段执行长时间任务:https://fangjunyu.com/2024/12/14/ios%e5%9c%a8%e5%90%8e%e5%8f%b0%e9%98%b6%e6%ae%b5%e6%89%a7%e8%a1%8c%e9%95%bf%e6%97%b6%e9%97%b4%e4%bb%bb%e5%8a%a1/