Navigating between different views depending upon the button clicked

Hi all, im trying to get a different view to appear depending upon the button clicked. For instance the memory button should navigate to memory view, the approaches button to the approaches view and so on. However, I only want the view to appear after the user has clicked the continue button on the bottom rather than navigating pages as soon as the user has clicked the topic. I have removed several other UI elements and other details from the code below that may not be as relevant to this question :)

(Right now regardless of the button clicked it defaults to the memory view page)

Any help would be greatly appreciated! As a first time swift coder who only started about three weeks ago its very easy to get confused!

import SwiftUI

struct ContentView: View {


	@State private var setMemory = false

	@State private var setSocialInfluence = false

	@State private var setApproaches = false

	@State private var setPsychopathology = false

	@State private var setBiopsychology = false

	@State private var setAttachment = false

	@State private var setIssuesandDebates = false

	@State private var setSchizophrenia = false

	@State private var setResearchMethods = false

	

	let buttons = ["10", "20", "30", "40", "50"]

	@State public var NumberSelected: Int?

	
	//Creating Variables for 'Continue' Button

	let button = ["Continue"]

	@State public var buttonContinue: Int?

	

	//Making Sure User Selects Topic(s) and Number of Questions

	private var allTopics: [Bool] {

		[setMemory, setSocialInfluence, setApproaches, setPsychopathology, setBiopsychology, setAttachment, setIssuesandDebates, setSchizophrenia, setResearchMethods]}

	

	private var TopicSelected: Bool {

		allTopics.contains { $0 }}

	

	private var isFormValid: Bool {

		TopicSelected && NumberSelected != nil}

	

	var body: some View {


		NavigationView {

			ScrollView{


					//Toggles for Topics and Vertical Stacks

					//Used Group{} to Prevent Argument Error

					Group{

						VStack(alignment: .leading, spacing: 5) {

							Toggle("Memory",isOn: setMemory)

								.toggleStyle(.button)

								.tint(Color(red: 0.902, green: 0.755, blue: 0.161))

							Toggle("Approaches",isOn: setApproaches)

								.toggleStyle(.button)

								.tint(Color(red: 0.945, green: 0.442, blue: 0.022))

							Toggle("Biopsychology",isOn: setBiopsychology)

								.toggleStyle(.button)

								.tint(Color(red: 0.817, green: 0.065, blue: 0.287))

							Toggle("Issues & Debates",isOn: setIssuesandDebates)

								.toggleStyle(.button)

								.tint(Color(red: 0.399, green: 0.06, blue: 0.947))

							Toggle("Research Methods Year 1 & 2",isOn: setResearchMethods)

								.toggleStyle(.button)

							.tint(Color(red: 0.105, green: 0.561, blue: 0.896))}

						.padding(.leading, -135.0)

						.padding(.top, -10)

						

						VStack(alignment: .leading, spacing: 5) {

							Toggle("Social Influence",isOn: setSocialInfluence)

								.toggleStyle(.button)

								.tint(Color(red: 0.902, green: 0.755, blue: 0.17))

							Toggle("Psychopathology",isOn: setPsychopathology)

								.toggleStyle(.button)

								.tint(Color(red: 0.945, green: 0.442, blue: 0.022))

							Toggle("Attachment",isOn: setAttachment)

								.toggleStyle(.button)

								.tint(Color(red: 0.817, green: 0.065, blue: 0.287))

							Toggle("Schizophrenia",isOn: setSchizophrenia)

								.toggleStyle(.button)

							.tint(Color(red: 0.394, green: 0.061, blue: 0.943))}

						.padding(.top, -192)

						.padding(.leading, 180)

					}

					

				HStack(spacing: 15) {

					ForEach(0..<button.count, id: \.self) {button in

						Button(action: {

							self.buttonContinue = button

							

						}) {

							

							//Links Continue Button To Next Page
NavigationLink(destination: MemoryView()) {

								Text("Continue")

							}

							

							.padding(.vertical, 12.5)

							.padding(.horizontal, 120)

							.foregroundColor(.white)

							.foregroundStyle(.background)

							.background(2 == button ? Color.primary: Color.secondary)

							

							//'Continue' Button is Disabled if User Has Not Selected Values

							.clipShape(Capsule())}}.disabled(!isFormValid)

					

				}

				

				Spacer()

				

			}

			

			//Allows Navigation Through Pages

			.navigationTitle("")

			.padding(.top, -100)

			

		}

	}

	

	

	struct Previews_ContentView_Previews: PreviewProvider {

		static var previews: some View {

			ContentView()

			

		}

	}

	

}
Answered by Claude31 in 709787022

You should use isActive in the NavigationLink:

So, I would define the Link for each button (with an isActive),

NavigationLink(
    "Name x",
    destination: DestinationView(), // different for each
    isActive: $shouldFire[x])

have a State var (shouldFire, array of Bool or use each of State var as setMemory) to keep what is the button to fire, then turn on in Continue Button the right link.

Accepted Answer

You should use isActive in the NavigationLink:

So, I would define the Link for each button (with an isActive),

NavigationLink(
    "Name x",
    destination: DestinationView(), // different for each
    isActive: $shouldFire[x])

have a State var (shouldFire, array of Bool or use each of State var as setMemory) to keep what is the button to fire, then turn on in Continue Button the right link.

Well, I had to restructure the code a little bit, making more use of State var, putting things in arrays, using ViewBuilder to select the appropriate destination…

Here it is (in 2 parts because of post limit):

struct MemoryView: View {
    var body: some View {
        Text("Memory")
    }
}

struct SocialView: View {
    var body: some View {
        Text("Social")
    }
}

struct ApproachesView: View {
    var body: some View {
        Text("Approaches")
    }
}

struct PsychopathologyView: View {
    var body: some View {
        Text("Psychopathology")
    }
}

struct BiopsychologyView: View {
    var body: some View {
        Text("Biopsychology")
    }
}

struct AttachmentView: View {
    var body: some View {
        Text("Attachment")
    }
}

struct IssuesandDebatesView: View {
    var body: some View {
        Text("IssuesandDebates")
    }
}

struct SchizophreniaView: View {
    var body: some View {
        Text("Schizophrenia")
    }
}

struct ResearchMethodsView: View {
    var body: some View {
        Text("ResearchMethods")
    }
}

struct ContentView: View {

    let kSetMemory          = 0
    let kSetSocialInfluence = 1
    let kSetApproaches      = 2
    let kSetPsychopathology = 3
    let kSetBiopsychology   = 4
    let kSetAttachment      = 5
    let kSetIssuesandDebates = 6
    let kSetSchizophrenia   = 7
    let kSetResearchMethods = 8

    @State var topicSelected : [Bool] = [false, false, false, false, false, false, false, false, false]

    @State var isActive = false // We can activate link
    @State var fire = false     // we fire link

    func resetOthers(except: Int) {
        isActive = topicSelected[except]    // The link will be activated
        if !topicSelected[except] { return }
        for k in kSetMemory...kSetResearchMethods where k != except {
            topicSelected[k] = false
        }
    }
    
    @ViewBuilder func destination(topic: Int) -> some View {
        switch topic {
            case kSetMemory:
                MemoryView()
            case kSetSocialInfluence:
                SocialView()
            case kSetApproaches:
                ApproachesView()
            case kSetPsychopathology:
                PsychopathologyView()
            case kSetBiopsychology:
                BiopsychologyView()
            case kSetAttachment:
                AttachmentView()
            case kSetIssuesandDebates:
                IssuesandDebatesView()
            case kSetSchizophrenia:
                SchizophreniaView()
            case kSetResearchMethods:
                ResearchMethodsView()
            default:
                EmptyView()
        }
    }

    private var topicNumber: Int? {
        for k in 0..<topicSelected.count {
            if topicSelected[k] { return k }
        }
        return nil
    }
    
    private var isFormValid: Bool { // One and only one selected
        topicSelected.filter({ $0 }).count == 1
    }

And the second part:

    var body: some View {

        NavigationView {

            ScrollView {
                    //Used Group{} to Prevent Argument Error

                Group {
                    VStack(alignment: .leading, spacing: 5) {
                        Toggle("Memory",isOn: $topicSelected[kSetMemory])
                            .toggleStyle(.button)
                            .tint(Color(red: 0.902, green: 0.755, blue: 0.161))
                            .onChange(of: topicSelected[kSetMemory], perform: { value in resetOthers(except: kSetMemory) } )
                        
                        Toggle("Approaches",isOn: $topicSelected[kSetApproaches])
                            .toggleStyle(.button)
                            .tint(Color(red: 0.945, green: 0.442, blue: 0.022))
                            .onChange(of: topicSelected[kSetApproaches], perform: { value in resetOthers(except: kSetApproaches) } )
                        
                        Toggle("Biopsychology",isOn: $topicSelected[kSetBiopsychology])
                            .toggleStyle(.button)
                            .tint(Color(red: 0.817, green: 0.065, blue: 0.287))
                            .onChange(of: topicSelected[kSetBiopsychology], perform: { value in resetOthers(except: kSetBiopsychology) } )
                        
                        Toggle("Issues & Debates",isOn: $topicSelected[kSetIssuesandDebates])
                            .toggleStyle(.button)
                            .tint(Color(red: 0.399, green: 0.06, blue: 0.947))
                            .onChange(of: topicSelected[kSetIssuesandDebates], perform: { value in resetOthers(except: kSetIssuesandDebates) } )
                        
                        Toggle("Research Methods Year 1 & 2",isOn: $topicSelected[kSetResearchMethods])
                            .toggleStyle(.button)
                        .tint(Color(red: 0.105, green: 0.561, blue: 0.896))
                        .onChange(of: topicSelected[kSetResearchMethods], perform: { value in resetOthers(except: kSetResearchMethods) } )

                    }
                    
                    .padding(.leading, -135.0)
                    .padding(.top, -10)
                    
                    VStack(alignment: .leading, spacing: 5) {
                        
                        Toggle("Social Influence",isOn: $topicSelected[kSetSocialInfluence])
                            .toggleStyle(.button)
                            .tint(Color(red: 0.902, green: 0.755, blue: 0.17))
                            .onChange(of: topicSelected[kSetSocialInfluence], perform: { value in resetOthers(except: kSetSocialInfluence) } )

                        Toggle("Psychopathology",isOn: $topicSelected[kSetPsychopathology])
                            .toggleStyle(.button)
                            .tint(Color(red: 0.945, green: 0.442, blue: 0.022))
                            .onChange(of: topicSelected[kSetPsychopathology], perform: { value in resetOthers(except: kSetPsychopathology) } )

                        Toggle("Attachment",isOn: $topicSelected[kSetAttachment])
                            .toggleStyle(.button)
                            .tint(Color(red: 0.817, green: 0.065, blue: 0.287))
                            .onChange(of: topicSelected[kSetAttachment], perform: { value in resetOthers(except: kSetAttachment) } )

                        Toggle("Schizophrenia",isOn: $topicSelected[kSetSchizophrenia])
                            .toggleStyle(.button)
                        .tint(Color(red: 0.394, green: 0.061, blue: 0.943))}
                    .onChange(of: topicSelected[kSetSchizophrenia], perform: { value in resetOthers(except: kSetSchizophrenia) } )

                    .padding(.top, -192)
                    .padding(.leading, 180)
                }
                
                Spacer()
                Spacer()

                Button(action: {
                    fire = true
                }) {
                    NavigationLink(destination: destination(topic: topicNumber ?? 10), isActive:  $fire) { // 10 just to have value
                        Text("Continue")
                    }
                    .padding(.vertical, 12.5)
                    .padding(.horizontal, 120)
                    .foregroundColor(.white)
                    .foregroundStyle(.background)
                    .background(isFormValid ? Color.red: Color.gray)

                    //'Continue' Button is Disabled if User Has Not Selected Values
                    .clipShape(Capsule())
                }
                .disabled(!isFormValid)
            }

            .navigationTitle("Select domain")
            .padding(.top, 20)
        }
    }

Thankyou so much for this! I really appreciate it :)

Navigating between different views depending upon the button clicked
 
 
Q