SwiftUI @Environment 環境變數教學
當你的 App 層級很深時,如果要把資料從最上層傳到最下層(例如:使用者設定、色彩主題、登入狀態),一層一層透過 @Binding 傳遞會非常痛苦且難以維護。這時候就是 Environment (環境) 登場的時候了。
@EnvironmentObject (自定義環境資料)
這相當於 SwiftUI 的「依賴注入 (Dependency Injection)」。你可以在最上層注入一個資料物件,底下所有子視圖(無論多深)都可以直接存取它。
步驟 1: 注入 (Inject)
在父視圖使用 .environmentObject() 修飾符。
@StateObject var userSettings = UserSettings()
var body: some View {
ContentView()
.environmentObject(userSettings) // 注入環境
}
步驟 2: 讀取 (Read)
在任意深度的子視圖中,宣告 @EnvironmentObject 即可直接使用,不需要初始化。
struct DeepChildView: View {
@EnvironmentObject var settings: UserSettings // 自動從環境中尋找
var body: some View {
Text("目前主題: \(settings.theme)")
}
}
如果在子視圖宣告了
@EnvironmentObject 但父視圖忘記注入,App 會在執行時崩潰 (Crash)。@Environment (系統環境值)
除了我們自定義的物件,SwiftUI 提供了許多內建的環境值 (Environment Values),例如:亮/暗模式、系統語系、畫面尺寸類別等。
我們使用 @Environment 並透過 KeyPath 來讀取這些值。
struct MyView: View {
@Environment(\.colorScheme) var colorScheme // 獲取目前是 Light 或 Dark mode
@Environment(\.dismiss) var dismiss // 獲取關閉視圖的方法
@Environment(\.openURL) var openURL // 獲取打開瀏覽器的方法
var body: some View {
if colorScheme == .dark {
Text("暗黑模式")
}
Button("關閉") {
dismiss()
}
}
}
Environment 機制極大地簡化了全域資料的共享與傳遞,是構建大型 App 不可或缺的工具。