1

I'm trying to prevent swiping to the second tab until the user has clicked a button on the first tabbed view indicating the data is complete. Then the user can swipe. I thought it was @State in the first tab view since it's the source of truth and a @Binding in the main content view, but that didn't work. I've simplified the code and removed the Binding info so that at least it will build. Any thoughts or better approach appreciated. (Quite new at this...)

//ContentView.swift file

struct ContentView: View {
    
    @State private var selection = 0
    @State var allowSwipeTo2 = false

    var body: some View {
        VStack {
            Text("Main Content View")
            Text(String(allowSwipeTo2)) //added this line, and can see it change from false to true when button is clicked, but still not swipable

                .font(.system(size: 18))
        }
        
        TabView(selection: $selection){
            tab1View(allowSwipeTo2: $allowSwipeTo2) //modified based on recommendation
                .tag(0)
    
            if allowSwipeTo2 == true {
                tab2View()
                    .tag(1)
            }
            }.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
    }
}

//tab1View.swift file with the button and the booleans for disabling further changes and ok to swipe:

struct tab1View: View {
    @State private var p8_10 = 0
    @State private var stepperDisabled = false
    @Binding var allowSwipeTo2: Bool  //modified based on recommendation
    @State private var showingAlert = false

    var body: some View {

        VStack{
            HStack{
                Text("Things")
                Stepper("Total: \(p8_10)", value: $p8_10, in: 0...15)
            }.font(.system(size: 15))
                .disabled(stepperDisabled)
            
            HStack{
                Spacer()
                
                Button("Entry Complete") {
                    showingAlert = true
                    
                }.alert(isPresented: $showingAlert){
                    Alert(
                        title: Text("Entry Complete?"),
                        message: Text("You will no longer be able to change your entry"),
                        primaryButton: .cancel(),
                        secondaryButton: .destructive(
                            Text("OK"),
                            action:{
                                stepperDisabled = true
                                allowSwipeTo2 = true
                            })
                    )
                }
                Spacer()
            }
        }
    }
}

//tab2View.swift file

struct tab2View: View {
    var body: some View {
        Text("Tab 2 Content!")
            .font(.system(size: 15))
    }
}```
darkenney
  • 37
  • 1
  • 6

1 Answers1

2

Small wrong approach. In your ContentView, you are supposed to bind the allowSwipeTo2 variable with the tab1View.

To fix your problem, change the type of variable allowSwipeTo2 in tab1View to @Binding var allowSwipeTo2 : Bool, and finally in your ContentView, call the first tab view like this tab1View(allowSwipeTo2: $allowSwipeTo2)

I have modified the code as below. You can find the modified parts with this comment //modified.

struct ContentView: View {

@State private var selection = 0
@State var allowSwipeTo2 = false

var body: some View {
    VStack {
        Text("Main Content View")
            .font(.system(size: 18))
    }
    
    TabView(selection: $selection){
        tab1View(allowSwipeTo2: $allowSwipeTo2) //modified
            .tag(0)

        if allowSwipeTo2 == true {
            tab2View()
                .tag(1)
        }
        }.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
}
}


struct tab1View: View {
@State private var p8_10 = 0
@State private var stepperDisabled = false
@Binding var allowSwipeTo2 : Bool //modified
@State private var showingAlert = false

var body: some View {

    VStack{
        HStack{
            Text("Things")
            Stepper("Total: \(p8_10)", value: $p8_10, in: 0...15)
        }.font(.system(size: 15))
            .disabled(stepperDisabled)
        
        HStack{
            Spacer()
            
            Button("Entry Complete") {
                showingAlert = true
                
            }.alert(isPresented: $showingAlert){
                Alert(
                    title: Text("Entry Complete?"),
                    message: Text("You will no longer be able to change your entry"),
                    primaryButton: .cancel(),
                    secondaryButton: .destructive(
                        Text("OK"),
                        action:{
                            stepperDisabled = true
                            allowSwipeTo2 = true
                        })
                )
            }
            Spacer()
        }
    }
}
}



struct tab2View: View {
var body: some View {
    Text("Tab 2 Content!")
        .font(.system(size: 15))
}
}
Steven-Carrot
  • 2,368
  • 2
  • 12
  • 37
  • Made those two changes, but it still doesn’t swipe unfortunately. I added the line Text(String(allowSwipeTo2)) to ContentView and I see it change from false to true, but still can’t swipe. – darkenney Jul 23 '22 at 12:00
  • Edit your code with what you have changed. – Steven-Carrot Jul 23 '22 at 12:04
  • updated above, just made the two changes you had recommended and added the Text(..) in ContentView to see the change happen. (Also the other solutions involving drag gesture don't work.) Thanks for the support. – darkenney Jul 23 '22 at 12:35
  • 1
    I copied pasted your code and ran immediately without any problem. I could swipe after the data became true. Did you try testing it in simulator or real device? You sure you could not swipe after the data became true? I tested on both simulator and real device. – Steven-Carrot Jul 23 '22 at 12:42
  • 1
    Ok, good to know your copy paste worked. I'm positive it doesn't swipe after data turns true. When I hard code 'true' into the code, it swipes, but not when the button click creates the true condition. I even copied the code above back into my project. Learning/testing on real device only. (Simulator running slows everything to a crawl on my older Mac.) – darkenney Jul 23 '22 at 13:01
  • 1
    A day later and was never able to use that bound bool value to prevent swiping. I was able to use it in virtually the same manner by specifying .disabled(true) on the second tab view until tab1 was final. So, still swipeable but can’t enter data until tab 1 complete. Just not understanding what’s happening, but thank you for your efforts getting me a solution and testing. Very much appreciated. – darkenney Jul 24 '22 at 01:23