I created an iOS app with SwiftUI and Swift. The aim is as follows:
- Consumer enters an deal with into an enter discipline
- On submit, the app sends the deal with to a backend
- The backend responds with a listing of experiences (e.g. snowboarding areas, climbing trails and many others.) close by
- Whereas the decision to the backend has not completed, the app exhibits a
ProgressView
loading animation - When the decision is finished, the loading animation ought to disappear and the app ought to swap to
ResultView
and show a listing of outcomes
Drawback: All is okay till I attain step 5. The ResultView
(with all the outcomes appropriately rendered) is seen for a break up second after which the app jumps again to AddressInputView
.
Query: Why is the app leaping again to the earlier view (As a substitute of staying in ResultView) and the way can the code be adjusted to repair the problem?
My Code:
StartView.swift
struct StartView: View {
var physique: some View {
NavigationStack {
AddressInputView()
}
}
}
AddressInputView.swift
enum Vacation spot {
case consequence
}
struct AddressInputView: View {
@State var radius = 300 // In meters
@State var isLoading = false
@State non-public var deal with: String = ""
@State non-public var experiences: [Experience] = []
@State non-public var path = NavigationPath()
func onSubmit() {
if !deal with.isEmpty {
Activity {
do {
strive await fetch()
} catch {
print("Error (error.localizedDescription)")
}
}
}
}
func fetch() async throws {
experiences.removeAll()
isLoading = true
let apiKey = Bundle.fundamental.object(forInfoDictionaryKey: "BACKEND_API_KEY") as? String ?? ""
let backendUrl = Bundle.fundamental.object(forInfoDictionaryKey: "BACKEND_URL") as? String ?? ""
let escapedAddress = deal with.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? ""
let params = "deal with=(escapedAddress)&radius=(radius)"
let fullUrl = "(backendUrl)/experiences?(params)"
var request = URLRequest(url: URL(string: fullUrl)!)
request.httpMethod = "GET"
request.allHTTPHeaderFields = [
"X-API-Key": apiKey
]
let session = URLSession.shared
let (knowledge, _) = strive await session.knowledge(for: request)
let serviceResponse = strive JSONDecoder().decode(ExperienceServiceResponse.self, from: knowledge)
deal with = serviceResponse.deal with
experiences = serviceResponse.experiences
isLoading = false
path.append(Vacation spot.consequence)
}
var physique: some View {
NavigationStack(path: $path) {
if isLoading {
ProgressView()
} else {
VStack {
TextField("", textual content: $deal with, immediate: Textual content("Search deal with"))
.onSubmit {
onSubmit()
}
Button(motion: onSubmit) {
Textual content("Submit")
}
.navigationDestination(for: Vacation spot.self, vacation spot: { vacation spot in
swap vacation spot {
case .consequence:
ResultView(deal with: $deal with, experiences: $experiences)
}
})
}
}
}
}
}
ExperienceModels.swift
struct ExperienceServiceResponse: Codable {
let deal with: String
let experiences: [Experience]
}
ResultView.swift
struct ResultView: View {
@Surroundings(.presentationMode) var mode: Binding<PresentationMode>
@Binding non-public var deal with: String
@Binding non-public var experiences: [Experience]
init(deal with: Binding<String>, experiences: Binding<[Experience]>) {
_address = Binding(projectedValue: deal with)
_experiences = Binding(projectedValue: experiences)
}
var physique: some View {
NavigationStack {
ScrollView {
VStack(alignment: .main) {
Textual content("Outcomes")
ForEach(experiences, id: .identify) { expertise in
ResultTile(expertise: expertise)
}
}
}
}
}
}