定義 App 的進入點與上層架構。
SwiftUI App 架構概覽
SwiftUI 定義式的語法除了用在 View,也用在定義 App 架構。我們會讓最上層的 struct 遵從 App protocol,並在裡面用不同的 Scene 來決定要呈現畫面。
SwiftUI 跨平台的特性讓我們能一次為所有的 Apple 平台撰寫程式,同時也能和 UIKit、AppKit、WatchKit 共存,去使用它們的 App delegate 以實做個別平台的 Callback,在 SwiftUI 要橋接其他框架的 AppDelegate 需要在最上層的 App 裡定義 AppDelegateAdaptor,裡面便能實作各平台 AppDelegate 裡有的 func。
當我們用 SwiftUI 建立專案時,定義 app 的 structure 會自動遵從 App protocol,並用必要的 computed property body
來定義 app 要顯示的內容。
@main
struct Example: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
在 structure 前的 @main 是用來指示說這是我們 App 的進入點,並且因為 App protocol 預先實作了 main()
方法來讓系統呼叫以啟動 App,這裡的 ContentView()
就會是我們 App 打開來的第一個畫面!
App 由 Scene 組成
在 body 裡,我們會用多個 Scene 來組出我們的 App,而每個 Scene 都有一個由系統管理生命週期的 root view。SwiftUI 提供了不同的 Scene 來滿足不同的需求,如:用來呈現檔案的 DocumentGroup 或顯示設定的 Settings ,而一般的 App 畫面都是使用 WindowGroup 。當然,我們也能自己實作客製的 Scene。
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
Settings {
SettingsView()
}
}
}
這裡值得注意的是,並不是所有 App 的 body 裡都需要定義多個 Scene,因為像 iOS、watchOS 只會有一個視窗,那就只需要一個 Scene。而像 macOS、iPadOS、visionOS 可以有多個視窗,就可以定義多個 Scene。
跨 Scene 的 state
我們可以在 App 的這一層定義 state,因為這裡是 App 的最上層,可能會有多個 Scene,所以在這裡的 State 能橫跨多個 Scene 共用,同步狀態!例如,我們可以在一開始就初始化整個 App 都會用到的資料,然後傳給每個 Scene 裡的 View,這樣每個畫面就會有一模一樣的資料,不需要各個畫面都重新去抓資料,也多虧了 @StateObject
讓我們不用擔心會有資料不同步的情況。
@main
struct Mail: App {
@StateObject private var model = MailModel()
var body: some Scene {
WindowGroup {
MailViewer()
.environmentObject(model)
}
Settings {
SettingsView(model: model)
}
}
}
關於 XcodeProject
XcodeProject 創立於 2023,致力於協助開發者探索 Apple 的創新世界,學習在 iOS、iPadOS、macOS、tvOS、visionOS 與 watchOS 上開發 App,發現眾多技術與框架,讓開發者獲得更多能力。