🐡
SwifUIのStateObject, ObservedObject, EnvironmentObjectで出来ること
使用優先度
違いがわからない場合、以下のような優先度で使用するものを選ぶのもいいと思います。
-
@StateObject// 最優先 @ObservedObject@EnvironmentObject
StateObjectで出来ないこと
以下のことはできないので、以下のようなことがしたい場合は、ObservedObjectを使用しましょう
MainViewでカウントアップしてSubViewでカウントを表示する
struct ContentView: View {
var body: some View {
MainView()
}
}
class Counter: ObservableObject {
var count: Int
init(count: Int) {
self.count = count
}
}
struct SubView: View {
@StateObject var counter: Counter
let date = Date()
var body: some View {
Text("\(counter.count)")
Text(date.formatted(.iso8601))
}
}
struct MainView: View {
@State var count: Int = 0
var body: some View {
Button("Count++") { count += 1 }
SubView(counter: .init(count: count))
}
}
EnvironmentObjectで出来ること
EnvironmentObjectは何もしなくても子Viewの子Viewに対してObjectを使用することができます。
以下の例ではSubSubViewを表示しているSubViewはEnvironmentに関して何も触れられていないですが、SubSubViewでは利用可能です。
class Counter: ObservableObject {
var count: Int
init(count: Int) {
self.count = count
}
}
struct SubView: View {
var body: some View {
SubSubView()
}
}
struct SubSubView: View {
@EnvironmentObject var counter: Counter
let date = Date()
var body: some View {
Text("\(counter.count)")
Text(date.formatted(.iso8601))
}
}
struct MainView: View {
@State var count: Int = 0
var body: some View {
Button("Count++") { count += 1 }
SubView()
.environmentObject(Counter(count: count))
}
}
まとめ
| Name | Description |
|---|---|
| StateObject | 自身のViewことしかわからない |
| ObservedObject | 親Viewのことも監視(Observe)している |
| EnvironmentObject | どこかの親ViewでenvironmentObjectされていいれば使用可能 |
Tips
@Bindingと@StateObjectを組み合わせれば@ObservedObject的な形で利用可能だが、ほぼうまくいかないので諦めが必要な場合あり
Discussion