How to push a new View onto NavigationStack after Async call

Viewed 442

I'm trying to learn the basics of SwiftUI ( coming from UIKit ).

I'm simply trying to push a new View once my async call is finished, but I don't find how.

This is my test implementation :

struct MasterView: View {

    @State var parralaxOffset: CGFloat = 0

    func handleParralax(_ reader: GeometryProxy) -> some View {
        self.parralaxOffset = reader.frame(in: .global).minY
        return Text("Foreground contentOffset: \(reader.frame(in: .global).minY)")
    }

    var body: some View {
        NavigationView {
            Group {
                Button(action: {
                    self.dummyAsynCall() {
                        //Push a new view
                    }
                }) {
                    Text("Button")
                }
            }
        }.navigationBarTitle("test")
    }

    private func dummyAsynCall(_ onComplete: @escaping (() -> ())) {
        DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
            print("Call completed")
            onComplete()
        }
    }
}

I know about NavigationLink but they work synchronously (when a user taps it basically).

Does anyone know how to perform the navigation in the completion block ?

1 Answers

You need to use NavigationLink(destination: tag: selection:) and add a @State var, i had called this as finished then you need to use NavigationLink(destination: tag: selection:) where tag will be the expected value in this case true, and in selection parameter you need to pass the @State var in this case $finished

import SwiftUI

struct LandmarkList: View {
    @State var finished : Bool? = nil
    let landmark = landmarkData[0]
    var body: some View {

        NavigationView {
            VStack {
                NavigationLink(destination: LandmarkDetails(currentLandmark:  self.landmark), tag: true, selection: self.$finished) {
                    Button(action: {
                        self.dummyAsynCall() {
                                  self.finished = true
                              }
                          }) {
                              Text("Button")
                          }
                }
            }

        }.navigationBarTitle("test")

    }

    private func dummyAsynCall(_ onComplete: @escaping (() -> ())) {
        DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
            print("Call completed")
            onComplete()
        }
    }
}

you can find better explanation here ;) https://mecid.github.io/2019/07/17/navigation-in-swiftui/

Related