この記事では、@ObservedObjectの使い方を解説していきたいと思います。
@ObservedObject とは?
簡単に言うと、@ObservedObjectとは、@Stateを複数同時に宣言できるクラスのことです。
@Stateの場合は、Viewごとに変数を宣言して使いますが、@ObservedObjectはクラスなので複数の変数をまとめて宣言して、複数のViewから使うことができます。
厳密にはちょっと違いますが、イメージ的にはこんな感じです。
使い方
使い方としては、ObservableObject
を準拠させたclass内に、@Stateの代わりに@Publishedを定義して、使いたいViewで@ObservedObjectで宣言して使います。
ちょっとややこしいので、サンプルコードを見ながら解説していきます。
以下のコードが@ObservedObjectを使ったサンプルコードです。
import SwiftUI class Fruits: ObservableObject { @Published var name = "りんご" @Published var price = 100 } struct ContentView: View { @ObservedObject var fruits = Fruits() var body: some View { VStack { Text("\(fruits.name)一個\(fruits.price)円です") .padding() Button("10円値上げする") { fruits.price += 10 } } } }
まず、FruitsというObservableObjectプロトコルに準拠したclassを定義します。
その中に、@Publishedをつけて変数を宣言します。@Publishedは@Stateと同じようなものだと思ってください。
そして、使いたいViewで@ObservedObjectをつけてfruitsという名前でインスタンス化します。
インスタンス化したら、fruits.nameや、fruits.priceと言うふうに@Stateと同じく使えます。値の更新をすると@Stateと同じく再描画されすぐに画面に反映されます。
別のViewと共有する
まとめて共有する
@Stateの場合は、@Bindingで渡していましたが、@ObservedObjectの場合は、インスタンスで渡してあげると全てのデータまとめて渡すことができます。
以下のコードは、BViewでfruitsの名前を変更するサンプルコードです。
class Fruits: ObservableObject { @Published var name = "りんご" @Published var price = 100 } struct ContentView: View { @ObservedObject var fruits = Fruits() @State var isShowBView = false var body: some View { VStack { Text("\(fruits.name)一個\(fruits.price)円です") .padding() Button("10円値上げする") { fruits.price += 10 } .padding() Button("BViewへ遷移") { isShowBView = true } } .sheet(isPresented: $isShowBView) { BView(fruits: fruits) } } } struct BView: View { @ObservedObject var fruits: Fruits var body: some View { Button("みかんに変える") { fruits.name = "みかん" } } }
BViewで、@ObservedObject var fruits: Fruits
というように書くことで、@Bindingのように、ContentViewのfruitsと紐づけることができます。
一部分だけ共有する
@Stateと同じく1つの値なら、@Bindingでも渡すことができます。挙動的には上記と全く変わりません。
class Fruits: ObservableObject { @Published var name = "りんご" @Published var price = 100 } struct ContentView: View { @ObservedObject var fruits = Fruits() @State var isShowBView = false var body: some View { VStack { Text("\(fruits.name)一個\(fruits.price)円です") .padding() Button("10円値上げする") { fruits.price += 10 } .padding() Button("BViewへ遷移") { isShowBView = true } } .sheet(isPresented: $isShowBView) { BView(fruitsName: $fruits.name) } } } struct BView: View { @Binding var fruitsName: String var body: some View { Button("みかんに変える") { fruitsName = "みかん" } } }
まとめ
まとめると、@ObservedObjectというのは、@Published(@Stateのようなもの)をまとめたクラスです。使うときはインスタンス化して使います。