So I've made a Button view in my body and I have set it's action to a Google Sign In action, but I want it to also transition to a new view when the sign in flow is completed. The problem is that I have set the label of the button to a Navigation Link and when I click it, it directly transitions to a next view. How can I delay the transition? For context, VoucherView is the next view I want to transition to.
Button {
guard let clientID = FirebaseApp.app()?.options.clientID else { return }
// Create Google Sign In configuration object.
let config = GIDConfiguration(clientID: clientID, serverClientID: GlobalConstants.BACKEND_SERVER_REQUEST_ID_TOKEN)
guard let presenter = CommonHelper.GetRootViewController() else {return}
// Start the sign in flow!
GIDSignIn.sharedInstance.signIn(with: config, presenting: presenter) {user, error in
if let error = error {
print (error.localizedDescription)
return
}
guard
let authentication = user?.authentication,
let idToken = authentication.idToken
else {
print ("Something went wrong!")
return
}
print (authentication)
print (idToken)
let credential = GoogleAuthProvider.credential(withIDToken: idToken,
accessToken: authentication.accessToken)
print (credential)
UserManager.shared.firebaseAuthentication(credential: credential)
signed = true
}
} label: {
NavigationLink {
VoucherView()
} label: {
Text("Sign In")
}
}
Edit: After I tried using isValid as a @State variable, after every cycle of SignIn and SignOut the screen goes down.
CodePudding user response:
Instead of using NavigationLink
inside your Button
, you can use a NavigationLink
with an EmptyView
for a label and then activate it programmatically with the isActive
parameter.
See the following example -- the Google Sign In process is replaced by just a simple async closure for brevity.
struct ContentView: View {
@State private var navigateToNextView = false
var body: some View {
NavigationView {
VStack {
Button {
DispatchQueue.main.asyncAfter(deadline: .now() 1) {
navigateToNextView = true
}
} label: {
Text("Sign in")
}
NavigationLink(destination: View2(), isActive: $navigateToNextView) { EmptyView()
}
}
}.navigationTitle("Test")
}
}
struct View2 : View {
var body: some View {
Text("Next view")
}
}
A couple more notes:
- Note that there has to be a
NavigationView
(make sure it's just one) in the hierarchy for this to work - In general, async work is better done in an
ObservableObject
than in aView
. You can consider moving your login function to anObservableObject
and making thenavigateToNextView
a@Published
property on that object.