🐡
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