この記事では、@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のようなもの)をまとめたクラスです。使うときはインスタンス化して使います。
