swiftswiftuiwatchoswatchos-6

SwiftUI NavigationLink not pushing view programmatically


I am having issues with pushing a view in SwiftUI by using a NavigationLink.

Currently I have it set up so that a binding boolean is set to "true" depending on whether a login was successful or not. However, when I run the code, the view is not pushed despite the boolean being successfully changed.

I am using Swift 5 and developing on WatchOS 6.2, which does NOT require the NavigationLink to be nested in a NavigationView since it's not supported.

import SwiftUI

struct Login: View {
    @State var pushErrorView = false
    @State var pushActivityView = false

    var body: some View {
        VStack{
            Button(action:
            {
                self.login()
            }) {
                Text("Log In")
            }
            
            NavigationLink(destination: PopupMessage(message: "Login Error"), isActive: self.$pushErrorView) {
                EmptyView()
            }.hidden()
            
            NavigationLink(destination: ActivityView(), isActive: self.$pushActivityView) {
              EmptyView()
            }.hidden()
        }
    }
    
    private func login(){         
        if loginSuccess() {
             self.pushActivityView = true                    
        }
        else {
             self.pushErrorView = true
        }
    }
}

Solution

  • Here is working solution. Tested with Xcode 11.4 / watchOS 6.2 on replicated code (due to absent dependent components).

    struct Login: View {
        @State var pushErrorView = false
        @State var pushNextView = false
    
        var body: some View {
            VStack{
                Button(action:
                {
                    self.login()
                }) {
                    Text("Log In")
                }.background(
                    NavigationLink(destination: Group {
                        if pushErrorView { PopupMessage(message: "Login Error") }
                        else { ActivityView() }
                    }, isActive: self.$pushNextView) { EmptyView() }
                )
            }
        }
    
        private func login(){
             self.pushErrorView = !loginSuccess()
             self.pushNextView = true
        }
    }