【SwiftUI】@EnvironmentObjectの使い方

SwiftUIのデータバインディングの仕組みの一つで、アプリケーション全体でデータを共有する為の@EnvironmentObjectの使い方を解説します。

その他のデータバインディングについてはこちらの記事を御覧ください。

【SwiftUI】データバインディング
SwiftUIのデータバインディングの仕組みである@State、@ObservedObject、@EnvironmentObject各々の特徴について解説します。

スポンサーリンク

環境

この記事の情報は次のバージョンで動作確認しています。

【Xcode】12.2
【Swift】5.3.1
【iOS】14.2
【macOS】Catalina バージョン 10.15.7
スポンサーリンク

@EnvironmentObjectの概要

@ObserverdObjectと同様に、ObservableObjectプロトコルに準拠したデータクラス(classのインスタンス)とViewを紐付ける仕組みです。
@ObserverdObjectとの違いは、バケツリレーのように子Viewに引き渡す必要がありません。インスタンスを階層トップのViewに紐付けると、アプリケーション全体からアクセス可能になります。
アプリケーション全体で共有するようなデータを扱う用途で使用します。

スポンサーリンク

インスタンスの生成と紐付け

EnvironmentObjectは、多くの場合アプリケーションのトップView生成時に、データクラスの生成と紐付けを行います。
紐付けにはenvironmentObjectモディファイアを使用ます。

アプリケーションのトップView生成箇所は、Xcodeで新規プロジェクト生成時に選択した「Life Cycle」によって変わります。

UIKit App Delegate

Xcode11で生成した新規プロジェクトはこちらのケースです。

このケースではSceneDelegate.swiftの中でトップView(ContentView)を生成しますので、ここでデータクラスを紐付けます。
ここでは例としてUserクラスのインスタンスを紐付けます。

SwiftUI App

Xcode12以降で新規プロジェクトを生成した場合はLife Cycleが選択可能です。
SwiftUI Appを選択した場合がこちらのケースになります。

このケースでは「プロジェクト名App.swift」の中で、トップView(ContentView)を生成しますので、ここでデータクラスを紐付けます。

スポンサーリンク

各Viewから共通インスタンスにアクセスする方法

このように@EnvironmentObjectを付けて、対象クラス型のプロパティを宣言します。
宣言したプロパティ(user)を使って、トップビューに紐付けられた共通インスタンスにアクセスできます。

使用例

次のサンプルを実行する際には、前章に従って、アプリケーションのトップビューにUserクラスのインスタンスが紐付けられている必要があります。

Text、TextField、Button全てが同じUserクラスのインスタンスを共有していますので、名前を変更したり、レベルアップボタンをタップすると、TextViewが自動で再描画されます。

使用例

スポンサーリンク

複数のインスタンスを紐付ける場合

次のようにenvironmentObjectモディファイアを重ねて、異なるクラスのインスタンスをアプリに紐付け可能です。
同じクラスのインスタンスの複数紐付けはできません。

スポンサーリンク

使用上の注意点

@EnvironmentObjectは、祖先ビューに紐付けられている必要があります。SwiftUIが正しいタイプのEnvironmentObjectを見つけられない場合、クラッシュが発生します。これはプレビューにも当てはまりますので、注意してください。

以下はプレビューでの記述例です。

スポンサーリンク

あわせて読みたい記事

【SwiftUI】データバインディング
SwiftUIのデータバインディングの仕組みである@State、@ObservedObject、@EnvironmentObject各々の特徴について解説します。
【SwiftUI】@Stateの使い方
(2021/05/22 更新) SwiftUIのデータバインディングの仕組みの一つである、@Stateについて解説します。 プロパティが更新された場合に、参照しているViewも同時に更新される仕組みが実現できます。 その他のデータバインディ...
【SwiftUI】@ObservedObjectの使い方
(2020/11/28 更新) SwiftUIのデータバインディングの仕組みの一つで、データクラスの更新を監視する@ObservedObjectの使い方を解説します。 これを利用すると複数のViewから同一インスタンスへの同期が可能になりま...