はじめに
iOS17以降からObservation
という新たな状態監視のFrameworkが使用できるようになりました。
しかし、状態監視のFrameworkとしてはすでにCombine
が存在しています。
今回は新たに登場したObservation
とCombine
を比較しながら、Observation
について見ていきます。
Observation
について
まずは、Observation
とCombine
の書き方を比較していきます。
今回はボタンをタップすると表示されている数字がインクリメントしていくViewをそれぞれ作成して比較していきます。
Combine
による状態監視
CounterViewState
はObservableObject
を実装し、@Published
を付与したプロパティの値を監視しています。
CounterView
はStateObject
を使ってCounterViewState
を監視可能なオブジェクトとしてインスタンス化することで、CounterViewState
の状態が変化した際にViewを再描画します。
import Combine
final class CounterViewState: ObservableObject {
@Published private(set) var count = 0
func increment() {
count += 1
}
}
import SwiftUI
struct CounterView: View {
@StateObject private var state: CounterViewState = .init()
var body: some View {
VStack {
Text(state.count.description)
Button("increment", action: {
state.increment()
})
}
.padding()
}
}
Observation
による状態監視
@Observable
はマクロで実装されている機能です。
@Observable
付与することで状態の変化を監視するようコードを変換してくれます。
Combine
と違い、@Published
をプロパティに付与しなくとも値を監視してくれます。
CounterView
は@State
を使ってCounterViewState
の値を監視、更新時にViewを再描画します。
import Observation
@Observable final class CounterViewState {
private(set) var count = 0
func increment() {
count += 1
}
}
import SwiftUI
struct CounterView: View {
@State private var state: CounterViewState = .init()
var body: some View {
VStack {
Text(state.count.description)
Button("increment", action: {
state.increment()
})
}
.padding()
}
}
Observation
とCombine
の違いについて
それぞれの実装を見てきました。
では実際には、Observation
とCombine
にはどういった違いがあるかを見ていきたいと思います。
Observation
とCombine
には大きく二つの違いがあります。
監視対象のプロパティの定義方法の違い
Combine
では監視対象のプロパティには@Published
をつける必要があります。
Observation
では必要なプロパティ一つ一つに@Published
をつけるといった冗長な作業は必要なく、通常通り定義するだけで問題ありません。
@Published
をプロパティ一つ一つにつけていくのは冗長だったので、付与する必要がなくなったのは単純に嬉しいですね。
オブジェクトの監視対象の違い
ObservableObject
を監視する場合、プロパティ毎の個別の変更を監視しているわけではなくObservableObject
のobjectWillChange
Publisherを監視しています。
objectWillChange
はObservableObject
のいずれかのプロパティが変更された際に発火します。
なので、Viewの描画に必要のないプロパティが更新された場合でも、不必要に再描画が走ってしまう等の可能性があります。
Observation
では、各プロパティを個別に監視しているため、関係のない値の変更によって不要な更新が走るといったことはありません。
Observation
で追加されたマクロ
Observation
には@Observable
の他に2つのマクロが追加されており、Observable
のプロパティに対してアノテーションとして付与することができます。
@ObservationTracked
@ObservationTracked
をプロパティに付与することで、プロパティの変更を検知するようコードを変換します。
が、基本的に開発者が@ObservationTracked
を使うことはありません。
@Observable
マクロによって、対象のプロパティを@ObservationTracked
を付与した形にコードを変換してくれるため、開発者が@ObservationTracked
を意識することはないでしょう。
@ObservationIgnored
@ObservationIgnored
をプロパティに付与することで、該当のプロパティを監視しないようコードを変換します。
Observation
では、Combine
のように@Published
を記載しなくてもプロパティの監視ができるようになっている反面、デフォルトで全てのプロパティを監視するようになっているので、監視の必要がない値には@ObservationIgnored
をつけてあげる必要があります。
import Observation
@Observable final class CounterViewState {
private(set) var count = 0 // 監視する
@ObservationIgnored private(set) var title = "" // 監視しない
}
最後に
Combine
よりもObservation
の違いを見てきましたが、やはりObservation
の方が使いやすそうだなといった印象です。
ただ、Observation
はiOS17以降でしか使えないため、既存のアプリに対しては即導入ということはできないので今後に期待です!
また、何かご意見等ありましたらコメントいただけますと幸いです。
どうぞよろしくお願いいたします。