【SwiftUI】@ObservedObjectの使い方

(2020/11/28 更新)

SwiftUIのデータバインディングの仕組みの一つで、データクラスの更新を監視する@ObservedObjectの使い方を解説します。
これを利用すると複数のViewから同一インスタンスへの同期が可能になります。

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

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

スポンサーリンク

環境

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

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

@Stateとの違い

データが更新されるとそのデータを参照しているViewも自動的に更新されるのがSwiftUIの特徴です。
@StateではViewのプロパティに対してその仕組みを実現しますが、データクラスに対しては@ObservedObjectを使用します。
@ObservedObjectを付けて宣言されたデータクラスのインスタンスは、SwiftUIの監視対象となり、プロパティが更新されると参照しているViewが自動的に再描画されます。

スポンサーリンク

基本的な使い方

名前とレベルを保持するUserクラスを例に説明します。

はじめに、対象とするクラスの定義を次のように記述します。

次にViewの中で対象のデータクラスを宣言をします。

ポイントは、次の3点です。

  1. データクラスはObservableObjectプロトコル準拠とする。
  2. 監視対象とするプロパティに@Published属性を付加する。
  3. データクラスのインスタンスは@ObservedObject属性を付加してViewの中で宣言する。

これで、@Published属性を付けたプロパティがSwiftUIの監視対象となり、値が変更されると参照しているViewが自動的に再描画されるようになります。

使用例

名前をいれてボタンをタップすると、プロパティを参照しているTextViewが再描画されます。

@ObservedObjectの使用例

スポンサーリンク

インスタンスを子Viewと共有する

Swiftのclassインスタンスは参照型ですので、そのまま子Viewに渡すだけで参照・更新が可能となります。
次のコードは入力フォームを別のViewに分割し、そちらからも同じインスタンスと同期をとる例です。
入力フォームView側でも共有するインスタンスを@ObservedObject属性を付けて宣言します。

バケツリレーのように、子Viewのさらに子Viewへと引き渡すのも可能です。

スポンサーリンク

インスタンスの一部プロパティだけ子Viewに渡すケース

インスタンスの一部プロパティだけを子Viewと共有したい場合は、@Stateで宣言されたプロパティと同様の方法が可能です。
子Viewに対しては、頭に$を付けてプロパティの参照値を渡し、子View側では@Bindingを付加して対象プロパティを宣言します。

以下はレベルアップボタンのみView分割した例です。

スポンサーリンク

あわせて読みたい記事

【SwiftUI】ObservableObjectを階層構造で使う
ObservableObjectを階層構造で扱う場合の注意点を解説します
【SwiftUI】データバインディング
SwiftUIのデータバインディングの仕組みである@State、@ObservedObject、@EnvironmentObject各々の特徴について解説します。
【SwiftUI】@Stateの使い方
(2021/05/22 更新) SwiftUIのデータバインディングの仕組みの一つである、@Stateについて解説します。 プロパティが更新された場合に、参照しているViewも同時に更新される仕組みが実現できます。 その他のデータバインディ...
【SwiftUI】@EnvironmentObjectの使い方
SwiftUIのデータバインディングの仕組みの一つで、アプリケーション全体でデータを共有する為の@EnvironmentObjectの使い方を解説します。 その他のデータバインディングについてはこちらの記事を御覧ください。
【SwiftUI】@ObservedObjectをCodable変換する方法
@ObservedObjectをCodable変換する方法について解説します。