Intercept custom action on TabView

Viewed 60

I was recommended to use the standard components so, instead of building my own TabView, I used SwiftUI's TabView. I only need a custom action that doesn't activate a view but triggers an action.

I almost succeeded to do it with the following code:

import SwiftUI

struct ContentView: View {
    @State var value: Int = 1

    private var adapterValue: Binding<Int> {
        Binding<Int>(get: {
            if (self.value == 4) {
                return 2
            } else {
                return self.value
            }
        }, set: {
            if $0 == 4 {
                self.value = 2
            } else {
                self.value = $0
            }
        })
    }

    var body: some View {
        TabView(selection: self.adapterValue, content:  {
            Text("A").tabItem {
                VStack {
                    Text("A")
                }
            }
            .tag(1)
            
            Text("B").tabItem {
                VStack {
                    Text("B")
                }
            }
            .tag(2)
            
            Text("C").tabItem {
                VStack {
                    Text("C")
                }
            }
            .tag(3)
            
            Text("D").tabItem {
                VStack {
                    Text("D")
                }
            }
            .tag(4)
        })
    }
}

It works well, except for when tab 2 (B) is activated and I press 4 (D), tab 4 (D) is activated. This should not happen, but I'm unsure what I'm missing.

I would like to understand the reason why this doesn't work as I expected and how I can prevent this behavior.

1 Answers

you could try this:

struct ContentView: View {
    @State var value: Int = 1
    
    var body: some View {
        TabView(selection: $value) {
            Text("A").tabItem {
                VStack {
                    Text("A")
                }
            }
            .tag(1)
            
            Text("B").tabItem {
                VStack {
                    Text("B")
                }
            }
            .tag(2)
            
            Text("C").tabItem {
                VStack {
                    Text("C")
                }
            }
            .tag(3)
            
            Text("D").tabItem {
                VStack {
                    Text("D")
                }
            }
            .tag(4)
        }
        .onChange(of: value) { val in
            if val == 4 {
                self.value = 2
            }
        }
    }
}
Related