はじめに
WWDC23で発表された新たなフレームワークのObservationの使い方を少しばかり勉強したのでアウトプットです。
今までのCombineとどのようにコードが変わるかを紹介していきます。
この記事でわかること
- Observationってどんなものか
- Observationを使ってとりあえずプログラムを動かす方法
- Combineと比較して何が変わったのか
想定読者
- SwiftUI触ったことあるよーという人
- ObservableObject使ったことあるよーという人
この記事で説明していないこと
- UIKitとObservationを合わせてどう使うかについて
-
@Bindable
などのプロパティラッパーについて
Observationって?
- WWDC23で発表された新たなフレームワークです
- Combineの進化系。みたいなイメージでいいと思いいます
- iOS17からのみ使用可能です
今回作るサンプル
- とてもシンプルなサンプルです。「add peach」ボタンタップするとリストに「もも」が追加されていきます。このサンプルを使って
Observation
の使い方をCombine
と比較しながら紹介します。ぜんぜん関係ないですが、「シンプルなサンプル」って韻踏んでていいっすね。
Combineを使った書き方
まずはCombineフレームワークに含まれるObservableObject
を使った書き方です
ViewModelのコード
import Combine
final class ObservableObjectFruitViewModel: ObservableObject {
@Published var fruits = ["りんご", "ばなな", "みかん", "ぶどう", "さくらんぼ"]
func tappedAddPeachButton() {
fruits.append("もも")
}
}
特徴
- クラスに
ObservableObject
プロトコルを準拠させます - 監視したいプロパティに
@Published
を付与します - 監視したいプロパティが複数あれば、全てに
@Published
を付与する必要があります
Viewのコード
import SwiftUI
struct ContentView: View {
@StateObject private var viewModel = ObservableObjectFruitViewModel()
~~ 省略 ~~
}
特徴
- viewModelのプロパティに
@StateObject
を付与
上記のように書くことで、viewModelのfruits
が監視され、変更が加わるとViewに自動的に反映されます。
では次にObservation
だとどのように書くことができるか紹介します。
Observationを使った書き方
ViewModelのコード
import Observation
@Observable
final class ObservationFruitViewModel {
var fruits = ["りんご", "ばなな", "みかん", "ぶどう", "さくらんぼ"]
func tappedAddPeachButton() {
fruits.append("もも")
}
}
特徴
- クラスに
@Observable
マクロを付与します -
@Observable
マクロを付与したクラスのプロパティは全て監視対象になります
Viewのコード
struct ContentView: View {
@State private var viewModel = ObservationFruitViewModel()
~~ 省略 ~~
}
特徴
- viewModelプロパティに
@State
を付与します。
上記のようにViewModelクラスには@Observable
マクロを付与し、View側のviewModelプロパティに@State
を付与することで、値を監視し、fruits
プロパティが変更されるとViewに反映されます。
ViewModelのプロパティを監視から外したい場合
Combine
@Published
を削除すれば監視対象から外れます。
final class ObservableObjectFruitViewModel: ObservableObject {
/* @Published */var fruits = ["りんご", "ばなな", "みかん", "ぶどう", "さくらんぼ"]
func tappedAddPeachButton() {
fruits.append("もも")
}
}
Observation
@ObservationIgnored
を付与すれば監視対象から外れます。
@Observable
final class ObservationFruitViewModel {
@ObservationIgnored ← これをつける
var fruits = ["りんご", "ばなな", "みかん", "ぶどう", "さくらんぼ"]
func tappedAddPeachButton() {
fruits.append("もも")
}
}
上記のように監視対象から外せば、ボタンをタップしてもリストは変化しません
Observationのうれしいところ
Observationを使用することで、ViewModelで監視対象にするプロパティ全てにいちいち@Published
を付与していく必要がないというのは楽ですね。付与し忘れるということも無くなりそうです。
それに加えてこの記事では詳しく書きませんが、@Binding
を使用した子Viewの更新にも差があります。
Observationを使用することで、変更があった子Viewのみを再描画するようになりました。これに関してはまたどこかで。
サンプルのViewのコード全体
- Observationを使った実装のViewのコードです。Combineを使っている場合はViewModelのクラスが変わります。
import SwiftUI
struct ContentView: View {
@State private var viewModel = ObservationFruitViewModel()
var body: some View {
VStack {
Button("add peach") {
viewModel.tappedAddPeachButton()
}
.padding(.vertical, 24)
List(viewModel.fruits, id: \.self) { item in
Text(item)
}
}
}
}
今回のサンプル
おわりに
WWDC23ではCombineについての発表もなかったみたいなので、今後はObservationの時代になっていきそうですね。
ではでは!!
参考