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

この記事からわかること

  • Swift UI独自EnvironmentValues定義する方法
  • @Environment使い方
  • 読み取り専用と変更可能な定義方法

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

EnvironmentValuesとは?

公式リファレンス:EnvironmentValues

EnvironmentValuesはSwift UIで使用できるアプリ内の環境値です。ここにはテーマやカラースキーム、フォント、ロケールなどアプリ全体で共通の設定を保持しています。シングルトンになってるイメージなのでビュー階層のどこからでも参照でき、参照や変更した値は常に共有されます。

おすすめ記事:EnvironmentValuesで取得できる値のキー一覧

EnvironmentValuesの値を参照するにはProperty Wrapper(プロパティラッパ)の@Environmentを使用します。@Environment読み取る値のキー値(\.キー値)形式で渡します。

@Environment(\.colorScheme) var colorScheme: ColorScheme

おすすめ記事:【Swift UI】@Environmentとは?使い方と使用可能なキー値一覧

EnvironmentValuesを独自に定義する

EnvironmentValues独自に定義することも可能になっています。これによりアプリ内で共有で管理したい環境設定などを簡単に共有させることが可能になります。

EnvironmentValuesとして定義する環境値は「読み取り専用」と「編集可能」の2パターンを実装することができます。

読み取り専用のEnvironmentValues

読み取り専用のEnvironmentValuesを定義するには以下のように定義します。

  1. EnvironmentKeyに準拠した構造体を定義
  2. EnvironmentValuesを拡張して参照する変数を定義
struct AppStateKey: EnvironmentKey {
    static let defaultValue: Int = 0
}

extension EnvironmentValues {
    var isAppState: Int {
        get { self[AppStateKey.self] }
        set { self[AppStateKey.self] = newValue }
    }
}

参照する際は@EnvironmentEnvironmentValues拡張して定義した変数名を指定します。読み取り専用なので値を格納しようとするとエラーになります。

struct ContentView: View {
    @Environment(\.isAppState) var isAppState
    var body: some View {
      Text("Hello")
            .onAppear {
                print(isAppState)
            }
    }
}

編集可能なEnvironmentValues

読み取り専用のEnvironmentValuesを定義する場合も手順は同じですが、データ型の部分をBinding<データ型>形式にします。

  1. EnvironmentKeyに準拠した構造体を定義
  2. EnvironmentValuesを拡張して参照する変数を定義
  3. 親Viewで@Stateで元となる変数を定義
  4. @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)
            }
    }
}

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index