SwiftUI 与传统的 UIKit 思路不同,是一种声明式 UI 框架,这种框架的特点就是摒弃了传统开发的代码按生命周期进行的流程概念,直接通过声明所呈现的内容来与用户进行交互。
App
swift
protocol App
App 代表了应用程序的抽象,需要在它的 body 属性中声明应用所能够呈现的内容:
swift
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
Text("Hello, world!")
}
}
}
在你的自定义实现结构体声明之上添加 @main
,用来标记这是应用程序的唯一主入口。同时,这也意味着你的应用程序只能有这一个主入口。
Scene
App 的 body 属性中,可以组合一个或多个 Scene 的实现,每一个 Scene 实现包含视图结构的根视图,代表用户界面中的内容,也可能是一部分(多窗口),它的生命周期由系统管理。
SwiftUI 提供了一些 Scene 的实现来表示场景的场景,包括显示设置或是文档。 你也可以自定义创建 Scene,但其实就是组合一些系统提供的 Scene:
swift
struct MyScene: Scene {
var body: some Scene {
WindowGroup {
MyRootView()
}
}
}
Scene 有一些常见实现:
- WindowGroup
- Settings
- Window
- ImmersiveSpace
- DocumentGroup
- ...
SwiftUI 是跨平台框架,所以基于不同的平台支持的 Scene 也有所不同。例如,visionOS 不支持 Window,而 ImmersiveSpace 是 visionOS 独有的。
App 的 body 中可以容纳一个或多个 Scene:
swift
@main
struct Mail: App {
var body: some Scene {
WindowGroup {
MailViewer()
}
Settings {
SettingsView()
}
}
}
应用启动,会默认打开第一个 Scene 所呈现的内容 。针对不同的平台,可能需要修改 plist 来支持多场景。例如,在 visionOS 平台或 iPadOS,需要添加 Enable Mutiple Windows 为 YES。
Scene 本质上就是呈现 View 结构的容器,系统会决定他们的显示行为,例如,在 iPadOS 或 macOS 支持多窗口,用户就可以创建或是删除一些窗口;而在 iOS 平台(or 其他)当应用处于活跃状态,视图内容将会占满整个屏幕。
Scene 的生命周期
可以通过环境值 scenePhase 来从 Scene 或 View 中读取当前 Scene 是否处于活跃状态:
swift
struct MyScene: Scene {
@Environment(\.scenePhase) private var scenePhase
// ...
}
scenePhase 是枚举类型 ScenePhase,包括:
- background:处于后台,不可交互;
- inactive:处于前台,不可交互;
- active:处于前台,可以交互。
Scene 提供了一些方法,可以对 Scene 进行配置,例如可以使用 onChange(of:perform)
来监听某个值的变化,从而触发一些操作,下面是一个当应用进入后台后清除缓存的操作:
swift
struct MyScene: Scene {
@Environment(\.scenePhase) private var scenePhase
@StateObject private var cache = DataCache()
var body: some Scene {
WindowGroup {
MyRootView()
}
.onChange(of: scenePhase) { newScenePhase in
if newScenePhase == .background {
cache.empty()
}
}
}
}
Scene 之间的通信
多个 Scene 可以通过在 App 中声明一些状态来进行通信。例如,使用 @StateObject 来初始化一个数据类,然后将数据类作为 ObservedObject 或通过环境作为 EnvironmentObject 提供给 Scene:
swift
@main
struct Mail: App {
@StateObject private var model = MailModel()
var body: some Scene {
WindowGroup {
MailViewer()
.environmentObject(model) // Passed through the environment.
}
Settings {
SettingsView(model: model) // Passed as an observed object.
}
}
}
总结
SwiftUI App 以 App 协议的实现为应用主入口,其 body 属性中可以配置多个 Scene,App 启动时默认打开第一个 Scene。 Scene 代表用户界面的容器,用来承载视图结构,其内容是视图结构的根视图。Scene 具有生命周期,包括三种:
- backgroud
- inactive
- active 可以通过环境属性 scenePhase 来查询。 Scene 直接可以通过在 App 中定义共享的数据结构来共享数据。可以通过一些方法或通过参数的形式传递到不同的 Scene。