SwiftUIの@ObservedObjectと@EnvironmentObjectの違いを説明する。
結論
両者とも目的は同じ。やり方が違うだけ。
- 両者とも目的は異なるView間で変数の値を連動させること。
- @ObservedObjectも@EnvironmentObjectを付けてObservableObjectに準拠するclassの型の変数を定義すると、そのclassの@Publishedを付けた変数は異なるView間で値が連動する。
- ObservableObjectに準拠するclassのインスタンスをViewに渡す際のやり方が違う。
– @ObservedObjectは個々のViewにそれぞれインスタンスを渡す。
– @EnvironmentObjectはあるViewに.environmentObject(インスタンス名)でインスタンスを渡す。それだけでそのView内の個々のViewはそのインスタンスと連動する。
具体例
下記Appを例に説明する。
- 親Viewのボタンをタップすると親ViewのヨシヒコのHPが10減る。
- 子Viewのボタンをタップすると子ViewのヨシヒコのHPが10回復する。
- 親Viewと子ViewのヨシヒコのHPは連動して変化する。
設計イメージ
@ObservedObjectを使う場合
@EnvironmentObjectを使う場合
コード
@ObservedObjectを使う場合
import SwiftUI
struct ContentView: View {
@StateObject var ヨシヒコ = ゆうしゃ()
var body: some View {
HStack {
// 親View
VStack {
Text("親View")
Text("ヨシヒコのHP : \(String(ヨシヒコ.HP))")
Button("ヨシヒコを攻撃") { ヨシヒコ.HP -= 10 }
.buttonStyle(.borderedProminent)
}
.padding()
.frame(width: 200)
// 子View
子View(キャラ: ヨシヒコ)
}
}
}
class ゆうしゃ: ObservableObject {
@Published var HP: Int = 100
}
struct 子View: View {
@ObservedObject var キャラ: ゆうしゃ
var body: some View {
VStack {
Text("子View")
Text("ヨシヒコのHP : \(String(キャラ.HP))")
Button("ヨシヒコを回復") { キャラ.HP += 10 }
.buttonStyle(.borderedProminent)
}
.padding()
.frame(width: 200)
.border(Color.black, width: 1)
}
}
@EnvironmentObjectを使う場合
import SwiftUI
struct ContentView: View {
@StateObject var ヨシヒコ = ゆうしゃ()
var body: some View {
HStack {
// 親View
VStack {
Text("親View")
Text("ヨシヒコのHP : \(String(ヨシヒコ.HP))")
Button("ヨシヒコを攻撃") { ヨシヒコ.HP -= 10 }
.buttonStyle(.borderedProminent)
}
.padding()
.frame(width: 200)
// 子View
子View()
}
.environmentObject(ヨシヒコ)
}
}
class ゆうしゃ: ObservableObject {
@Published var HP: Int = 100
}
struct 子View: View {
@EnvironmentObject var キャラ: ゆうしゃ
var body: some View {
VStack {
Text("子View")
Text("ヨシヒコのHP : \(String(キャラ.HP))")
Button("ヨシヒコを回復") { キャラ.HP += 10 }
.buttonStyle(.borderedProminent)
}
.padding()
.frame(width: 200)
.border(Color.black, width: 1)
}
}
差分
左が@ObservedObjectを使う場合、右が@EnvironmentObjectを使う場合
まとめ
SwiftUIの@ObservedObjectと@EnvironmentObjectの違いを説明した。
コメント