iosswiftuisegmentedcontrol

SwiftUI segmented control - how to switch to other segment on tap in first segment?


I have a segmentedControl (Picker) with two segments:

struct Container: View {    
    @State private var selectedSegment: Segment = .first
    
    var body: some View {
        VStack {
            Picker("", selection: $selectedSegment) {
                ForEach(Segment.allCases, id: \.self) {
                    Text($0.rawValue)
                }
            }
            .pickerStyle(.segmented)
            .padding()
            Spacer()
            SegmentView(segment: selectedSegment)
            Spacer()
        }
    }
}

struct SegmentView: View {
    var segment: Segment
    
    var body: some View {
        switch segment {
        case .first:
            FirstView()
        case .features:
            FeaturesView()
        }
    }
}

In one of the segments I show a list:

struct FeaturesView: View {
    private var features: [Feature]
        
    var body: some View {
        VStack {
            List(features) { feature in
                FeatureRow(feature: feature)
                    .onTapGesture {
                        // switch to other segment and pass in `feature`
                    }
            }
            .listStyle(PlainListStyle())
        }
    }
}

What I am trying to do is when the user taps on one of the rows in FeaturesView, switch to FirstView and pass in the feature.

How do I do this is SwiftUI ?

Maybe by using a Notification ?


Solution

  • Based on @PtitXav's comments this is what I came up with:

    struct Container: View {    
        @State private var selectedSegment: Segment = .first
        @State private var selectedFeature: Feature = Feature()
        
        var body: some View {
            VStack {
                Picker("", selection: $selectedSegment) {
                    ForEach(Segment.allCases, id: \.self) {
                        Text($0.rawValue)
                    }
                }
                .pickerStyle(.segmented)
                .padding()
                .onChange(of: selectedFeature) { s in
                    print(s)
                    selectedSegment = .sequence
                }
    
                Spacer()
                SegmentView(segment: selectedSegment, selectedFeature: $selectedFeature)
                Spacer()
            }
        }
    }
    
    struct SegmentView: View {
        @Binding var selectedFeature: Feature
    
        var segment: Segment
        
        var body: some View {
            switch segment {
            case .first:
                FirstView(selectedFeature: $selectedFeature)
            case .features:
                FeaturesView(selectedFeature: $selectedFeature)
            }
        }
    }
    
    struct FeaturesView: View {
        @Binding var selectedFeature: Feature
    
        private var features: [Feature]
            
        var body: some View {
            VStack {
                List(features) { feature in
                    FeatureRow(feature: feature)
                        .onTapGesture {
                            selectedFeature = feature
                        }
                }
                .listStyle(PlainListStyle())
            }
        }
    }