【Swift UI】@ObservedObjectと@StateObjectの違いについて 2023/12
ObservableObjectとは
ObservableObjectはプロトコルでありクラスに継承して使用します。
機能は、@publishedをつけた変数の値を監視して、変更されたらviewを更新します。
つまり、データバインディングをしてくれるプロトコルです。
@ObservedObjectと@StateObjectについて
@ObservedObjectと@StateObjectは、property wrapperです。つまり変数の値をを監視してくれます。
基本的にはviewで定義し、監視対象のデータやモデルが更新されるとviewを変更します。
@ObservedObjectと@StateObjectの違いは監視する範囲とライフサイクルです。
では、詳しく見ていきましょう!!
@ObservedObjectの使い方
-
まず、ObservedObjectを継承したクラスを用意し、変数に@publishedをつけ監視対象にします。
下記画像だと、
DataModelクラスにObservedObjectプロトコルを継承させており、
nameとisEnabledに@publishedをつけ変数の値を監視対象にしています。
変数の前に@publishedをつけ忘れると値が変わってもviewは更新されません。 -
次に、viewで変数に@ObservedObjectを宣言します。宣言することで、変数を監視します。
下記画像では、変数var model: DataModelに@ObservedObjectをつけることで、DataModelの変更を監視し、変更されるとViewを再描画します。
DataModelのnameを変えているので、Textで描画されるnameが「Some Name」から「勉強するマン」になります。
@ObservedObjectのライフサイクル
@ObservedObjectと@StateObjectの最大の違いがこのライフサイクルです。
つまり、インスタンス化したデータの内容を保持できる期間が違います。
@ObservedObjectと@StateObjectを使う最大のメリットは他のViewと情報を共有することです。
親ビューを作って@ObservedObjectのライフサイクルを見ていきましょう!
親ビューからzennViewを読んだ場合、@ObservedObjectのライフサイクルは親Viewのbodyが更新される度です。
つまり、下記画像だとoyaViewが何らかのアクションで再描画されるとzennViewのButtonを押してnameを「勉強するマン」に変えていても「Some Name」に戻ります。
要約
「@ObservedObjectのライフサイクルは親ビューが表示されてから消えるまで」
@StateObjectの使い方
@ObservedObjectと同じです。
監視したい変数があるクラスにObservedObjectを継承させて、変数に@publishedをつける。
そして、Viewの変数に@StateObjectを宣言する。
@StateObjectのライフサイクル
@StateObjectはViewが表示されてから非表示になるまでです。
つまり、oyaViewが再描写されようがzennViewに影響はございません。
zennViewのButtonを押してnameを「勉強するマン」に変えているとoyaViewが再描画されてもnameが「勉強するマン」のままです。
ただし、今回の例だとoyaViewの中にzennViewを作ってDataModelをインスタンス化しているので、oyaViewを消すとzennViewも消えて変更がリセットされます。
要約
「@StateObjectのライフサイクルは自身のViewが表示されてから非表示になるまで」
@ObservedObjectと@StateObjectの違いまとめ
使い方
違いはない。
@ObservedObjectと@StateObjectで同じ、Viewで宣言するときにどっちをつけるか
ライフサイクル
@ObservedObject | @StateObject |
---|---|
親ビューが表示されてから消えるまで | 自身のViewが表示されてから非表示になるまで |
@ObservedObjectを使うときの注意点
上記の使い方だと、自身のView(znnView)でDataModelをインスタンス化しているので、親ビューが再描写されるとライフサイクルが終了し値がリセットされる。
そのため、 @ObservedObjectではインスタンス化するのではなく、親Viewから渡されるデータを参照する場合に使うべきだと思います。
@StateObject var model: DataModelで、DataModelを参照する変数を宣言し、oyaViewでインスタンス化したDataModelを代入する。
自身のビュー | 親ビュー |
---|---|
全体コード
雑で申し訳ございませんが、今回説明に使った全体コードを載せます。
Discussion