amin89
amin89

Reputation: 437

How to switch to another view programmatically in SwiftUI (without a button press)

I have a problem to switch to another view without pressing a button in my SwiftUI app. I can take many examples of what I want to do : 1- Imagine a login form where we need to fill 2 textfields : username and password. When there's a perfect match we are automatically authenticated. 2- Take my example now. I have this view :

enter image description here

What I want to do : when I select a row in the list (ex. Lyon-Perrache TGV) AND if the two textfields are not empty => I'm redirected to another view.

There's many examples to know how to move to a view from another one, but always with a button click .. (with NavigationLink) I need to do this programatically exactly when the two textfields are filled AND when I select the destination textfield from the list.

that's a part of my code :

import SwiftUI



struct Search: View {



 @ObservedObject var webservice = Webservice()

 @State var Depart: String = ""

 @State var Destination: String = ""

 @State var listStation = [Station]()

 @State var predictedValues: Array<String> = []

 @State var isBeingEditedDeparture: Bool = false

 @State var isBeingEditedDestination: Bool = false

 @State var hey: Bool  = false

 @State var activate: Bool  = false



init() {

      UITableView.appearance().showsVerticalScrollIndicator = false

      UITableView.appearance().backgroundColor = .clear

      UITableViewCell.appearance().backgroundColor = .clear

      //UITableView.appearance().separatorColor = .clear

  }



var body: some View {





    VStack(alignment: .leading){



        PredictingTextField(listStation: self.$listStation , predictedValues: self.$predictedValues, 
        Depart: self.$Depart, Destination: self.$Destination, isBeingEditedDeparture: 
        self.$isBeingEditedDeparture, isBeingEditedDestination: self.$isBeingEditedDestination )



            .textFieldStyle(RoundedBorderTextFieldStyle())



        List() {

            ForEach(self.predictedValues, id: \.self){ value in



                Text(value)

                    .onTapGesture {

                        if(self.isBeingEditedDeparture == true)

                        {

                            self.Depart = value

                        }

                        else{

                            self.Destination = value
                            self.activate = true

                        }

                }

            }

        }.padding(.top, 10)



    }

}

I have declared a variable named "activate" to be the trigger point of moving to the new View. It's equal to true when we select a row in the list for "destination" textfield.

How can I do to go further ?

Thank you in advance !

error

Upvotes: 6

Views: 5717

Answers (2)

Kirill I.
Kirill I.

Reputation: 47

The idea is something about this:

When isActive comes true, NavigationLink is activated and goes to destination, like if you click on content inside NavigationLink() { content() }

struct SomeView: View {
    @State private var isActive = false
    NavigationView {
        NavigationLink(
            destination: ViewThatOpensWhenIsActiveComesTrue(),
            isActive: $isActive
        ) {
            // your custom case that u talking about in question
            // for example, with button its can be used like that:
            Button("Activate isActive") {
                isActive = true
            }
        }
    }
}

Upvotes: 0

pawello2222
pawello2222

Reputation: 54426

iOS 16+

Note: Below is a simplified example of how to programatically present a new link. For a more advanced generic example please see this answer.

In iOS 16 we can access the NavigationStack and NavigationPath that allow us to push views programmatically.

struct ContentView: View {
    @State private var path = NavigationPath()

    var body: some View {
        NavigationStack(path: $path) {
            Text("ContentView")
                .navigationDestination(for: String.self) { view in
                    if view == "NewView" {
                        Text("NewView")
                    }
                }
        }
        .onAppear {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                path.append("NewView")
            }
        }
    }
}

In the above example you can trigger the NewView to appear just by executing path.append("NewView") from any place.

iOS 13-15

You can use a NavigationLink with the isActive parameter. When you set this parameter to true it will present a NewView:

@State var activated: Bool = false
NavigationLink(destination: NewView(), isActive: $activated) {
    EmptyView()
}

Then you need to place your NavigationLink in the NavigationView to make it work.

Upvotes: 10

Related Questions