I created an iOS app with SwiftUI and Swift. The purpose is as follows:
- User enters an address into an input field (
AddressInputView
) - On submit, the app switches to
ResultView
and passes the address
Problem: The ResultView
is visible for just a split second and then suddenly jumps back to AddressInputView
.
Question: Why is the app jumping back to the previous view (Instead of staying in ResultView) and how can the code be adjusted to fix the issue?
My Code:
StartView.swift
struct StartView: View {
var body: some View {
NavigationStack {
AddressInputView()
}
}
}
AddressInputView.swift
enum Destination {
case result
}
struct AddressInputView: View {
@State private var address: String = ""
@State private var experiences: [Experience] = []
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
VStack {
TextField("", text: $address, prompt: Text("Search address"))
.onSubmit {
path.append(Destination.result)
}
Button("Submit") {
path.append(Destination.result)
}
.navigationDestination(for: Destination.self, destination: { destination in
switch destination {
case .result:
ResultView(address: $address, experiences: $experiences)
}
})
}
}
}
}
ExperienceModels.swift
struct ExperienceServiceResponse: Codable {
let address: String
let experiences: [Experience]
}
ResultView.swift
struct ResultView: View {
@Environment(\.presentationMode) var mode: Binding<PresentationMode>
@Binding private var address: String
@Binding private var experiences: [Experience]
init(address: Binding<String>, experiences: Binding<[Experience]>) {
_address = Binding(projectedValue: address)
_experiences = Binding(projectedValue: experiences)
}
var body: some View {
NavigationStack {
ScrollView {
VStack(alignment: .leading) {
Text("Results")
ForEach(experiences, id: \.name) { experience in
ResultTile(experience: experience)
}
}
}
}
}
}
CodePudding user response:
You have too many NavigationStack
s. This is a container view that should be containing your view hierarchy, not something that is declared at every level. So, amend your start view:
struct StartView: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
AddressInputView(path: $path)
}
}
}
AddressInputView
should take the path as a binding:
@Binding var path: NavigationPath
And you should remove NavigationStack
from the body of that view. Likewise with ResultView
. I made these changes in a project using the code you posted and the issue was fixed.
I'm not sure exactly why your view is popping back but you're essentially pushing a navigation view onto a navigation view onto a navigation view, so it's not entirely surprising the system gets confused.