SwiftUIでの@Environment — 定義、主な概念とメカニズム

著者: IT Sectr 公開日: 2026-06-25 読了時間: 8 分

SwiftUIの@Environmentは、システム環境から値を読み取るためのproperty wrapperであり、View術を自動的に伝播します。このコンポーネントは、カラースキーム、ロケール、フォントサイズ、managedObjectContext、その他多数のシステムパラメータへのアクセスを提供します。Apple Developer Documentation (2025)によれば、@Environmentは、環境値の変更がサブスクライブされたすべてのViewの再描画を引き起こし、マニュアルなコールなしでリアクティブなインタフェース更新を実現することを保証します。

メインポイント

  • @Environment — SwiftUIシステム環境値を読むためのproperty wrapper
  • カラースキーム、ロケール、フォントサイズはよく使われるシステム値
  • 変更はサブスクライブされたViewの自動再描画を引き起こす
  • カスタムキーでEnvironmentKeyを通じて独自の環境値を作成できる
  • @Environment — 読み取り専用; @EnvironmentObject — 書き込み用

SwiftUIでの@Environmentとは?

@Environmentは、システム環境から値を読み取るために設計されたSwiftUIのproperty wrapperです。環境は、SwiftUIが親Viewから子Viewへ自動的に伝播する値の階層的コンテナです。それぞれの環境値は、EnvironmentKeyプロトコルに従うタイプであるキーによって識別されます。

環境の仕組みは、フレームワークレベルでの依存性インジェクションに類似しています。システムは事前定義された値のセットを提供します — カラースキーム(ライト/ダーク)、ロケール、フォントサイズ、Core Data用のmanagedObjectContext、画面を閉じるためのdismiss、その他多数。特定のキーで@Environmentを宣言したViewは、現在の値を自動的に取得し、それが変わったときに再描画されます。

SwiftUI環境アーキテクチャは、EnvironmentValuesプロトコルに基づいています — すべてのシステム値を含む構造体です。それぞれの値は、getterとsetterを持つこの構造体のプロパティとして格納されます。@Environmentは、特定のプロパティにアクセスするためにkey pathを使用します: @Environment(\.colorScheme) — カラースキームへのアクセス、@Environment(\.locale) — ロケールへのアクセス。

Property Wrapperとしての@Environment

Property wrapper @Environmentは、2つの主な仕組みを実装しています: 環境から値を読み取り、その変化にサブスクライブすること。Viewが作成されると、SwiftUIはすべての@Environmentプロパティを経由し、現在のコンテキストから対応する値にリンクします。親Viewが.environment()修飾子を通じて値を変更すると、その値を読むすべての子Viewが自動的に再描画されます。

重要な機能: @Environmentはオプショナル値をサポートしています。階層で値が設定されていない場合、EnvironmentKeyで定義されたデフォルト値が返されます。システムキーの場合、デフォルト値はいつも合理的です — 例えば、デフォルトのカラースキームは.lightです。カスタムキーの場合、開発者がEnvironmentKeyプロトコルのdefaultValueメソッドでデフォルト値を定義します。

swift
struct EnvironmentReaderView: View {
    @Environment(\.colorScheme) var colorScheme
    @Environment(\.locale) var locale
    @Environment(\.sizeCategory) var sizeCategory

    var body: some View {
        VStack {
            Text("Current scheme: \(colorScheme == .dark ? "Dark" : "Light")")
            Text("Locale: \(locale.identifier)")
            Text("Font size: \(sizeCategory)")
        }
    }
}

例では、Viewが3つのシステム環境値を読み取っています。colorSchemeが変わったとき — 例えば、ユーザーが設定でダークモードを有効にしたとき — Viewは新しい値で自動的に再描画されます。同様に、地域やフォントサイズ(Dynamic Type)が変わった場合も同じです。Viewは通知にサブスクライブしたり、refreshをコールする必要がありません — SwiftUIがこれを自動的に管理します。

システム環境値

SwiftUIは、インタフェースと動作のさまざまな要素をカバーする数十のシステム環境値を提供しています。カラースキーム (\.colorScheme)は、ライトモードとダークモードにインタフェースを適応させることができる、もっともよく使われる値の1つです。ロケール (\.locale)には、日付、数値、通貨のフォーマットのためのユーザーのローカル設定が含まれます。

Core Dataでは、managedObjectContext (\.managedObjectContext)が使用されます — パーシステンスコンテナから環境を通じて渡されるコンテキストです。ナビゲーションには、現在の画面を閉じるためのdismiss (\.dismiss)と、モーダル表示のためのisPresented (\.isPresented)が利用可能です。カレンダーとタイムゾーンには — それぞれcalendarとtimeZoneがあります。

Key Pathタイプ目的
\.colorSchemeColorSchemeライトまたはダークモード
\.localeLocaleローカル設定
\.sizeCategoryContentSizeCategoryDynamic Typeフォントサイズ
\.managedObjectContextNSManagedObjectContextCore Dataコンテキスト
\.dismissDismissAction画面を閉じる
\.calendarCalendar現在のカレンダー
\.timeZoneTimeZoneタイムゾーン
\.horizontalSizeClassUserInterfaceSizeClass横並びスクリーンサイズ

システム値にアクセスするには、ドットでkey pathを使用します: @Environment(\.dismiss) var dismiss。コンパイラはEnvironmentValuesでのkey pathの存在を確認するため、間違ったキーはコンパイルタイムエラーを引き起こします。Appleは、iOSのバージョンごとに新しいシステム値を追加しています — 完全なリストはEnvironmentValuesドキュメンテーションで確認できます。

@Environment vs @EnvironmentObject

同じような名前にもかかわらず、@Environment@EnvironmentObjectは異なる目的を持ちます。@Environmentは、EnvironmentKeyを通じて登録されたシステムまたはカスタム値を読み取ります。@EnvironmentObjectは、明示的なキーなしで、タイプによって環境を通じて渡されるObservableObjectのproperty wrapperです。

@EnvironmentObjectは依存性インジェクションに使用されます: 親Viewがオブジェクト(例: ViewModel)を作成し、.environmentObject()修飾子を通じて子Viewに渡します。子Viewは@EnvironmentObjectを通じて受け取り、そのプロパティを読み取ったり変更したりできます。一方、@Environmentはシステム値のための読み取り専用であり、フィードバックをサポートしていません。

パラメータ@Environment@EnvironmentObject
目的システムおよびカスタム値ObservableObjectインジェクション
キーEnvironmentValuesのkey pathオブジェクトのタイプによる
書き込み読み取り専用読み取りと書き込み
カスタム値EnvironmentKeyを通じてObservableObjectクラスを通じて
デフォルト値あり (defaultValue)なし (渡す必要があり)

実務上: システムパラメータ(モード、ロケール、フォントサイズ)およびランタイムで変わらないカスタム設定にアクセスするには@Environmentを使用します。子コンポーネントから状態を変更する必要がある場合、View階層を通じてViewModelまたはサービスを渡すには@EnvironmentObjectを使用します。

@Environmentコード例

カスタム環境値の作成を見てみましょう。これには、EnvironmentKeyプロトコルに従う構造体を定義し、EnvironmentValuesを新しいプロパティで拡張する必要があります。これにより、プロパティを使わずに、アプリケーション設定やテーマ設定をViewツリー全体に渡すことができます。

swift
struct AppThemeKey: EnvironmentKey {
    static let defaultValue: AppTheme = .system
}

extension EnvironmentValues {
    var appTheme: AppTheme {
        get { self[AppThemeKey.self] }
        set { self[AppThemeKey.self] = newValue }
    }
}

enum AppTheme { case system, light, dark }

EnvironmentKeyプロトコルは、静的プロパティdefaultValueの実装を必要とします — これは、親Viewがカスタム環境を設定していない場合に使用される値です。EnvironmentValuesを拡張すると、キーでsubscriptを使用して、計算プロパティappThemeが追加されます。これにより、どのViewでも@Environment(\.appTheme)を通じて値を読み取ることができます。

カスタムキーでの@Environmentの使用

swift
struct ThemedView: View {
    @Environment(\.appTheme) var appTheme
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        VStack {
            if appTheme == .dark || (appTheme == .system && colorScheme == .dark) {
                Text("Dark mode active")
                    .foregroundStyle(.white)
                    .background(Color.black)
            } else {
                Text("Light mode active")
                    .foregroundStyle(.black)
                    .background(Color.white)
            }
        }
    }
}

struct ContentView: View {
    @State private var selectedTheme = AppTheme.system

    var body: some View {
        ThemedView()
            .environment(\.appTheme, selectedTheme)
    }
}

ThemedViewは2つの環境を読み取ります: カスタムのappThemeとシステムのcolorScheme。この組み合わせにより、軽柔なテーマ設定が可能になります: ユーザーは、ライト、ダーク、システムのテーマを選択できます。システムが選択された場合、値はcolorSchemeから取得され、iOS設定でテーマが切り替えられると自動的に変更されます。親View (ContentView)は.environment()修飾子を通じてappTheme値を設定します。

画面を閉じるためのdismissの使用

swift
struct ModalView: View {
    @Environment(\.dismiss) var dismiss
    @State private var name = ""

    var body: some View {
        NavigationStack {
            Form {
                TextField("Your name", text: $name)
                Button("Save") { dismiss() }
            }
            .navigationTitle("Edit Profile")
        }
    }
}

この例は、dismissの実用的な使い方を示しています — 環境からのDismissActionのインスタンスです。関数としてdismiss()を呼び出すと、モーダル画面が閉じるか、NavigationLinkが戻ります。唯一の条件は、Viewがモーダルで表示されているか、NavigationStack内にあることです。dismissはコンテキストから自動的に決定されます: Viewがsheetとして開かれていればsheetが閉じられ、popoverとして開かれていればpopoverが閉じられます。

よくある質問

子Viewから@Environmentの値を変更できますか?

いいえ、@Environmentは読み取り専用です。値を変更するには、ObservableObjectを伴う@EnvironmentObjectか@Bindingを使用してください。カスタムEnvironmentKeysには拡張でsetterを持てますが、これを通じての変更はUI更新をトリガーしません — 技術的には可能ですが、推奨されません。

@Environmentと@Bindingの違いは?

@Bindingは、真実のソース(State、StateObject、ObservableObject)への双方向接続を作ります。@Environmentは、階層コンテキストからの単方向読み取りです。@Bindingは子Viewへデータを渡すのに適し、@Environmentはシステムまたはグローバル設定にアクセスするのに適しています。

独自の環境値を作成するには?

静的なdefaultValueを持つEnvironmentKeyプロトコルを実装する構造体を定義します。その後、subscript[key]を使ったgetter/setterでプロパティを持つようにEnvironmentValuesを拡張します。登録後、読み取りには@Environment(\.yourKey)、設定には.environment(\.yourKey, value)を使用します。

SwiftUIで利用可能な環境値は?

SwiftUIは50以上のシステム値を提供しています: colorScheme, locale, sizeCategory, managedObjectContext, dismiss, calendar, timeZone, horizontalSizeClass, verticalSizeClass, accessibilityEnabled, layoutDirection, legibilityWeight、その他。完全なリストはEnvironmentValuesドキュメンテーションで確認できます。

@EnvironmentはPreviewで動作しますか?

はい、@EnvironmentはPreviewで動作しますが、デフォルト値がシミュレータと異なる場合があります。Previewでテストするには、Previewコードで直接.environment()修飾子を使用します: ThemedView().environment(\.colorScheme, .dark)。これにより、異なる環境状態を視的に確認できます。

まとめ

  • @Environment — key pathを通じてSwiftUIシステム環境値を読むためのproperty wrapper
  • カラースキーム、ロケール、フォントサイズ、managedObjectContextが最もよく使われるシステム値
  • 変更はサブスクライブされたすべてのViewの自動再描画を引き起こす
  • カスタムEnvironmentKeyでアプリケーション環境をグローバル設定で拡張できる
  • @Environment — 読み取り専用; @EnvironmentObject — 書き込みアクセス付きObservableObject用
  • .environment()修飾子で階層の子Viewに値を設定できる
  • 使い分け: @Environmentはシステムパラメータ用、@EnvironmentObjectはViewModel・サービス用

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください