2021/5/6
「ObservedObjectプロパティラッパーって何?」
「ObservedObjectプロパティラッパーの使い方を知りたいって人に向けて、この記事では書かれています」
どうも、ちょげ(@chogetarou)です。
SwiftUIでは、プロパティラッパーを使うことによって、変数に機能を付与できるようになりました。
プロパティラッパーには、いくつかあるのですが、その1つに@ObservedObjectがあります。
この記事では、@OvservedObjectプロパティラッパーについて解説します。
概要

@ObservedObjectは、クラスの変更を監視するためのプロパティラッパーです。
@Stateや@Bindingなどは、ビュー内で定義した変数の更新通知を受け取りますが、@ObservedObjectは自作クラス内で定義した、特定の変数の更新通知を受け取ります。
例えば、タイマーアプリで、タイマークラスという時間やタイマー設定を扱うクラスを扱うとします。
アプリでは、SwiftUIのビューからタイマーの時間の更新通知を受け取らないといけないんですよね。
そこで、タイマークラスの特定のプロパティが変更されたら、更新通知を受け取れるように@ObservedObjectをタイマークラスのインスタンスに使います。
使い方

@ObservedObject は使い方は、ちょっと特殊です。
@Stateなどと同じように変数の前に付けるだけでは、使えません。
おおまかな流れを説明すると
- 自作クラスをObservableプロトコルに準拠させる
- クラス内の監視したいプロパティに@Publishedを付ける
- 使用するビューでインスタンスに@ObservedObjectを付ける
1. ObservableObjectプロトコルへの準拠
なんか難しそうに聞こえますが、監視したいクラス名にプロトコル名を書くだけです。
class クラス名 : ObservableObject {
//プロパティ
//メソッド
}
プロトコルを使うことで、@ObservedObjectを付けれるようにします。
2. @Published プロパティ名
ノリとしては、@Stateみたいなものです。
クラス内で、変更された時に更新通知を送りたいプロパティに@Publishedを付けます。
1つだけ注意点を言うと、@PublishedはCombineフレームワークの機能です。
なので、クラス定義する前に、Combineフレームワークをインポートしておかなければなりません。
import Combine
//タイマークラスのタイムプロパティをパブリッシュする
class Timer: ObservableObject {
@Published time = 0
//定義
}
3. 使用するビューで@ObservedObject
ここまで出来たらあとは、使用するビュー内で、@ObservedObjectを使うだけです。
例えば、タイマークラスを使う場合であれば、
import SwiftUI
struct ContentView : View {
@ObservedObject var timer = Timer()
var body : some View {
//ビューの描画
}
}
注意点

ObservedObjectには、注意点があります。
それは、ドル記号($)の記述です。
@Stateや@Bindingなどでは、ドル記号は変数名の前に付けて使います。
しかし、ObservedObjectの場合は、クラス内のプロパティ名ではなく、インスタンスの変数名の前に付けます。
//@Stateの場合
$count
//@ObservedObjectの場合
$timer.time
//ダメな例
timer.$time
これに関しては、色々と複雑なので割愛しますが、簡単に言うとこのやり方じゃないと、正しく参照出来ないのです。
まとめ
ObservedObjectについてまとめると
- ビューで自作クラスの更新通知を受け取ることが出来る
- 使うには、3つのステップがある
1.自作クラスのObservableプロトコル準拠
2. Combineフレームワークの@Publishをプロパティに付ける
3. ObservedObjectをビュー内で使う - プロパティの参照を渡すときは、インスタンス名にドル記号をつける必要がある
読んで頂きありがとうございました。
コメント