【Swift UI】独自のEnvironmentValuesを定義する方法と使い方!

この記事からわかること
- Swift UIで独自のEnvironmentValuesを定義する方法
- @Environmentの使い方
- 読み取り専用と変更可能な定義方法
index
[open]
\ アプリをリリースしました /
環境
- Xcode:15.0.1
- iOS:17.0
- Swift:5.9
- macOS:Sonoma 14.1
EnvironmentValuesとは?
EnvironmentValues
はSwift UIで使用できるアプリ内の環境値です。ここにはテーマやカラースキーム、フォント、ロケールなどアプリ全体で共通の設定を保持しています。シングルトンになってるイメージなのでビュー階層のどこからでも参照でき、参照や変更した値は常に共有されます。
おすすめ記事:EnvironmentValuesで取得できる値のキー一覧
EnvironmentValues
の値を参照するにはProperty Wrapper(プロパティラッパ)の@Environment
を使用します。@Environment
に読み取る値のキー値を(\.キー値)
形式で渡します。
@Environment(\.colorScheme) var colorScheme: ColorScheme
おすすめ記事:【Swift UI】@Environmentとは?使い方と使用可能なキー値一覧
EnvironmentValuesを独自に定義する
EnvironmentValues
は独自に定義することも可能になっています。これによりアプリ内で共有で管理したい環境設定などを簡単に共有させることが可能になります。
EnvironmentValues
として定義する環境値は「読み取り専用」と「編集可能」の2パターンを実装することができます。
読み取り専用のEnvironmentValues
読み取り専用のEnvironmentValues
を定義するには以下のように定義します。
- EnvironmentKeyに準拠した構造体を定義
- EnvironmentValuesを拡張して参照する変数を定義
struct AppStateKey: EnvironmentKey {
static let defaultValue: Int = 0
}
extension EnvironmentValues {
var isAppState: Int {
get { self[AppStateKey.self] }
set { self[AppStateKey.self] = newValue }
}
}
参照する際は@Environment
にEnvironmentValues
を拡張して定義した変数名を指定します。読み取り専用なので値を格納しようとするとエラーになります。
struct ContentView: View {
@Environment(\.isAppState) var isAppState
var body: some View {
Text("Hello")
.onAppear {
print(isAppState)
}
}
}
編集可能なEnvironmentValues
読み取り専用のEnvironmentValues
を定義する場合も手順は同じですが、データ型の部分をBinding<データ型>
形式にします。
- EnvironmentKeyに準拠した構造体を定義
- EnvironmentValuesを拡張して参照する変数を定義
- 親Viewで@Stateで元となる変数を定義
- @Environmentと@Bindingを付与して変更可能にする
struct AppStateKey: EnvironmentKey {
static let defaultValue: Binding<Bool> = .constant(false)
}
extension EnvironmentValues {
var isAppState: Binding<Bool> {
get { self[AppStateKey.self] }
set { self[AppStateKey.self] = newValue }
}
}
Binding
で定義したら親Viewで元となる変数を@State
で定義しenvironment
で子ビューへと伝播させます。
@main
struct MyAppApp: App {
@State private var isAppState = false
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.isAppState, $isAppState)
}
}
}
@Environment
で取得する際に@Binding
も付与することで値の更新が可能になります。
struct ContentView: View {
@Environment(\.isAppState) @Binding var isAppState
var body: some View {
VStack {
Text(String(isAppState))
Button {
isAppState.toggle()
} label: {
Text(String(!isAppState))
}
}
}
}
@Binding
を付与しない場合は@Environment
で取得できるデータ型もBinding<データ型>
型になるので値を参照したい場合はwrappedValue
を使用します。
struct ContentView: View {
@Environment(\.isAppState) var isAppState
var body: some View {
CarouselView(width: 300, height: 200)
.onAppear {
print(isAppState.wrappedValue)
}
}
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。