[SwiftUI] ObservableObject, @ObservedObject, @Published を理解する

SwiftUI

@State と同様によく使われる ObservableObject, @ObservedObject, @Published を説明します。

@State は struct にしか使えない

@State は、struct (というか、value-type) にしか使えないんです。

見てみます。

example code

(1) で、@State の対象は、struct として定義しています。

StateWorksWell

[@State は、struct と組み合わせるとうまく動きます。]
Text で表示される値と、Stepper で変更する値が同期することが確認できます。

class に変えてみます。

example code

@State は、class に適用するとうまく動かない

[@State は、class に適用するとうまく動かない]
class に変えただけなのですが、値が変更されなくなります。実際には、値は変更されているのですが、変更されたことによるビューの更新がされなくなります。

“Check Value” ボタンでその時点での値を、Xcode のコンソールに出力することができます。出力してみると Stepper の + ボタンを押した数分増えた数値が、コンソールに表示されることが確認できます。ですので、値が変更されていないのではなく、ビューが更新されていないと確認できます。

つまり、@State は、class に対して使用すると、@Binding と組み合わせることで、値のリファレンスを渡すことはできていますが、その変更をフェッチし、ビューを更新することができていない ことがわかります。

まさしく、このケースが、@ObservedObject を使うケースとなります。

@ObservedObject

@ObservedObject の property wrapper を付与するためには、class が ObservableObject を conform していなければなりません。

@ObservedObject を使ったものを追記すると以下のようになります。

example code

実行してもらうとわかりますが、下側の UI は、期待通りに動作します。

ObservableObject は class とうまく動作する

「ObservableObject は class とうまく動作する」

ObservableObject とは? @Published とは?

ObservableObject とは、内部にobjectWillChange というプロパティを持つことを要求する Protocol です。objectWillChange のタイプは、Publisher です。

Apple のドキュメントは、こちら

@Published は、そのプロパティの変更について、上記の Publisher を使って、通知します。

@Published の projectedValue は、@Binding
なお、@Published が付与されたプロパティの $ を渡すと、@Binding になります。

まとめ

@State と @ObserervedObject
設定対象
@State struct, enum
@ObserervedObject class
ObservableObject と @Published
  • @ObservedObject として使用される class は、ObservableObject プロトコルに準拠するように定義されなければいけない
  • 変更を監視するプロパティに、@Published を付与する
  • @ObservedObject に含まれる @Published が付与されているプロパティは、@Binding で受ける

説明は以上です。
不明な点やおかしな点ありましたら、ご連絡いただけるとありがたいです。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です