🪶
NavigationStackで遷移して次のViewに状態を共有する
Wrapする位置に注意が必要
GitHub Copilot For XcodeやChatGPT、Claudeなど精度の高いAIを使ってもなぜか非推奨のNavigationLinkを使いたがる???
やりたいこととしては、@EnvironmentObject
を使用してObservableObject
で変更した状態を共有したい。
NavigationLink(destination: ChildView().environmentObject(countModel)) {
Text("子ビューへ移動")
.font(.title)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(15)
}
}
流石にこれは困る😅さすがにこ
こんな時は、stack overflowを見て同じ課題を見てみる。
でもnoteの記事の方が参考になった。
@State private var isPresented = false
を定義して、NavigationStack
でVStack
をWrapする。ボタンを押すと、isPresented = true
に変更することで画面遷移することができる。この時に、状態を他のViewに渡すコードを書く。
Button{
isPresented = true
} label: {
Text("子ビューを表示")
}
.navigationDestination(isPresented: $isPresented) {
ChildView()
.environmentObject(countModel)
}
全体のコード
import SwiftUI
class CountObservableObject: ObservableObject {
@Published var count: Int = 0
init(count: Int) {
self.count = count
}
// returnは戻り値がある
// Voidは戻り値がない
func increment() {
count += 1
}
}
struct ChildView: View {
@EnvironmentObject var countModel: CountObservableObject
var body: some View {
Text("子ビューのカウント: \(countModel.count)")
.font(.title)
.padding()
.onTapGesture {
countModel.increment()
}
}
}
struct ContentView: View {
@StateObject private var countModel = CountObservableObject(count: 0)
@State private var isPresented = false
var body: some View {
NavigationStack {
VStack {
Text("現在のカウント: \(countModel.count)")
.font(.largeTitle)
.padding()
Button(action: {
countModel.increment()
}) {
Text("カウントを増やす")
.font(.title)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(15)
}
}
.padding()
Button{
isPresented = true
} label: {
Text("子ビューを表示")
}
.navigationDestination(isPresented: $isPresented) {
ChildView()
.environmentObject(countModel)
}
}}
}
#Preview {
ContentView()
}
ボタンを押してカウントする。画面遷移して、他のページに状態を共有してみる。
はいできました🙌
ちなみに、@StateObject private var countModel = CountObservableObject(count: 0)
を呼び出せば表示できるだろうと思って実験したらカウントされてませんでした😇
なので、他のページに状態を共有するときには、@EnvironmentObject
は必要です。
最後に
状態を変更して他のページに値を共有するときは、@EnvironmentObject
が必要です。そして画面遷移するときは、NavigationStack
を使用するのが現在は推奨されていてNavigationLink
とは書き方が変わってますので注意が必要です。
Discussion