🗽
【SwiftUI】@StateObjectと@ObservedObjectの挙動の違い
概要
- StateObjectとObservedObjectの挙動の違いの動作確認を行ったのでメモする
実験1: 挙動の違いを見る
コード
DataSource.swift
class DataSource: ObservableObject {
@Published var count: Int = 0
}
- 親view自体に変更が食わられるようにする
ContentView.swift
struct ContentView: View {
@State private var count = 0
var body: some View {
VStack {
VStack {
Text("ContentView")
Text("@state count: \(count)")
Button("increment") {
count += 1
}
}
Spacer().frame(height: 30)
StateObjectView()
Spacer().frame(height: 30)
ObservedObjectView()
}
.padding()
}
}
- StateObjectを使ったviewと、ObservedObjectを使ったviewを容易
StateObjectView.swift
struct StateObjectView: View {
@StateObject private var dataSource = DataSource()
var body: some View {
VStack {
Text("StateObjectView")
Text("dataSource.count: \(dataSource.count)")
Button("increment") {
dataSource.count += 1
}
}
.background(Color.mint)
}
}
ObservedObjectView.swift
struct ObservedObjectView: View {
@ObservedObject private var dataSource = DataSource()
var body: some View {
VStack {
Text("ObservedObjectView")
Text("dataSource.count: \(dataSource.count)")
Button("increment") {
dataSource.count += 1
}
}
.background(Color.yellow)
}
}
結果
- 親viewに更新があったタイミングで、@ObservedObjectの方は初期化される
実験2: @ObservableObjectを活かす
コード
- 上記のviewを少し改変し、@StateObjectを利用するviewから、その子どものviewの@ObservableObjectにわたす場合を考える
StateObjectView.swift
struct StateObjectView: View {
@StateObject private var dataSource = DataSource()
var body: some View {
VStack {
Text("StateObjectView")
Text("dataSource.count: \(dataSource.count)")
Button("increment") {
dataSource.count += 1
}
ChildObservedObjectView(dataSource: dataSource)
}
.background(Color.mint)
}
}
ChildObservedObjectView.swift
struct ChildObservedObjectView: View {
@ObservedObject var dataSource: DataSource
var body: some View {
VStack {
Text("ChildObservedObjectView")
Text("dataSource.count: \(dataSource.count)")
Button("increment") {
dataSource.count += 1
}
}
.background(Color.yellow)
}
}
結果
- この状況であれば、親viewが更新されてもOK
- @ObservedObjectは、自身がデータソースとなってはいけないことがわかる
Discussion