2

I'm trying to do the simplest of things. I just want to summon a new SwiftUI view programmatically - not with a button, but with code. I've read a couple of dozens posts and Apple docs on this - but almost all that I've found relates to code that has been renamed or deprecated. The closest I have found is:

NavigationLink(destination: NewView(), isActive: $something) {
    EmptyView()
}

But this does not work for me in Xcode Beta 7. Here's the trivial app:

struct ContentView: View {
    @State private var show = false

    var body: some View {

        VStack {
            Text("This is the ContentView")

            Toggle(isOn: $show) {
                Text("Toggle var show")
            }
            .padding()

            Button(action: {
                self.show = !self.show
            }, label: {
                Text(self.show ? "Off" : "On")
            })
            Text(String(show))

            //this does not work - the ContentView is still shown
            NavigationLink(destination: SecondView(), isActive: $show)
            {
             EmptyView()
            }

            //this does not work - it adds SecondView to ContentView
            //I want a new view here, not an addition
            //to the ContentView()
//            if show {
//                //I want a new view here, not an addition to the ContentView()
//                SecondView()
//            }
        }
    }

}

And the brutally simple destination:

struct SecondView: View {
    var body: some View {
        Text("this is the second view!")
    }
}

I must be missing something extremely simple. Any guidance would be appreciated. iOS 13.1, Catalina 19A546d, Xcode 11M392r

JohnSF
  • 3,736
  • 3
  • 36
  • 72
  • As suggested, a `NavigationLink` needs to be inside a `NavigationView` to work. Look into using that - a *hidden* NavigationLink - along with the `isActive` modifier for pushing a view programmatically: https://stackoverflow.com/questions/57315409/push-view-programmatically-in-callback-swiftui/57321795#57321795 –  Sep 03 '19 at 02:24

1 Answers1

2

A couple of things. First, NavigationLink must be imbedded in a NavigationView to work. Second, the link doesn't need a view as you showed it. This should show the second view. I will leave to you to update the other elements.

 var body: some View {
    NavigationView{
        VStack {
            Text("This is the ContentView")

            Toggle(isOn: $show) {
                Text("Toggle var show")
            }
            .padding()

            Button(action: {
                self.show = !self.show
            }, label: {
                Text(self.show ? "Off" : "On")
            })
            Text(String(show))

            //this does not work - the ContentView is still shown
            NavigationLink(destination: SecondView()){
            Text("Click to View")}
            Spacer()
//                {
//                    EmptyView()
//                }

            //this does not work - it adds SecondView to ContentView
            //I want a new view here, not an addition
            //to the ContentView()
            //            if show {
            //                //I want a new view here, not an addition to the ContentView()
            //                SecondView()
            //            }
        }
    }
}
Michael Rivers
  • 920
  • 2
  • 10
  • 17
  • Thanks, Michael. Unfortunately that still does not work. The second view is still displayed at the end of the ContentView stack. I guess I could do some frame sizing to push the ContentView up, but that seems ridi – JohnSF Sep 03 '19 at 00:59
  • Actually, Michael's method does work. I had the entire VStack in a NavigationView and then added a second NavigationView around the NavigationLink so the result was pushing the SecondView essentially into the stack at the bottom. After removing that extra NavigationView the transition is as expected (except for a bug that repeats the load the first time). My erroneous duplication could be very useful when you do want to programmatically add a view to a stack. – JohnSF Sep 04 '19 at 00:42