Prasanth
Prasanth

Reputation: 676

How to display details screens from multiple enum picker selections in SwiftUI

I am using swiftui to update an app which can display a detail screen based on the users picker selection. I created a view for each detail screen(about 50) and I have a multi-picker for the user to select which detail screen to display. What is the best way to use the selections from the picker to show the appropriate detail view.

Here is an simplified example of the multi-picker:

struct PickerMenu: View {

    enum HypoHyper: String, CaseIterable, Identifiable {
        case Hypo
        case Hyper

        var id: String { self.rawValue }
    }

    enum Lytes: String, CaseIterable, Identifiable {
        case Na
        case K

        var id: String { self.rawValue }
    }

    enum Details: String, CaseIterable, Identifiable {
        case Causes
        case Signs

        var id: String { self.rawValue }
    }


    @State var selectedHypoHyper = HypoHyper.Hyper
    @State var selectedLyte = Lytes.Na
    @State var selectedDetail = Details.Causes


    var body: some View {
        GeometryReader { geometry in
            HStack {
                Picker(selection: self.$selectedHypoHyper, label: Text("")) {
                    ForEach(HypoHyper.allCases) { hypoHyper in
                        Text(hypoHyper.rawValue).tag(hypoHyper.rawValue)
                    }
                }
                .frame(width: geometry.size.width/3, height: 150, alignment: .center)
                .clipped( )
                Picker(selection: self.$selectedLyte, label: Text("")) {
                    ForEach(Lytes.allCases) { lyte in
                        Text(lyte.rawValue).tag(lyte.rawValue)
                    }
                }
                .frame(width: geometry.size.width/3, height: 150, alignment: .center)
                .clipped( )
                Picker(selection: self.$selectedDetail, label: Text("")) {
                    ForEach(Details.allCases) { detail in
                        Text(detail.rawValue).tag(detail.rawValue)
                    }
                }
                .frame(width: geometry.size.width/3, height: 150, alignment: .center)
                .clipped( )
            }

        }
    }
}

Upvotes: 0

Views: 276

Answers (2)

cedricbahirwe
cedricbahirwe

Reputation: 1396

Does this one helps, here we are using a switch statement and return a view (or a NavigationLink) depending on the context

switch (selectedHypoHyper, selectedLyte, selectedDetail) {
case (.Hyper, .Na, .Causes): EmptyView()
case (.Hyper, .Na, .Signs): EmptyView()
case (.Hyper, .K, .Causes): EmptyView()
case (.Hyper, .K, .Signs): EmptyView()
// Continue with other cases ...
default: EmptyView()
}

Upvotes: 1

there various ways to do this, here is a simple approach: (note I had to modify the Pickers)

@main
struct TestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct ContentView: View {
    var body: some View {
        NavigationView {
            PickerMenu()
        }.navigationViewStyle(StackNavigationViewStyle())
    }
}

// put these outside the PickerMenu for other views to use
enum HypoHyper: String, CaseIterable, Identifiable {
    case Hypo
    case Hyper
    var id: String { self.rawValue }
}

enum Lytes: String, CaseIterable, Identifiable {
    case Na
    case K
    var id: String { self.rawValue }
}

enum Details: String, CaseIterable, Identifiable {
    case Causes
    case Signs
    var id: String { self.rawValue }
}

struct PickerMenu: View {
    
    @State var selectedHypoHyper: HypoHyper = HypoHyper.Hyper
    @State var selectedLyte = Lytes.Na
    @State var selectedDetail = Details.Causes
    @State var showDetailView = false
    
    var body: some View {
        VStack (spacing: 30) {
            GeometryReader { geometry in
                HStack {
                    Picker("", selection: $selectedHypoHyper) {
                        ForEach(HypoHyper.allCases, id: \.id) { hypoHyper in
                            Text(hypoHyper.rawValue).tag(hypoHyper)
                        }
                    }
                    .frame(width: geometry.size.width/3, height: 150, alignment: .center)
                    .clipped( )
                    Picker("", selection: $selectedLyte) {
                        ForEach(Lytes.allCases, id: \.id) { lyte in
                            Text(lyte.rawValue).tag(lyte)
                        }
                    }
                    .frame(width: geometry.size.width/3, height: 150, alignment: .center)
                    .clipped( )
                    Picker("", selection: $selectedDetail) {
                        ForEach(Details.allCases, id: \.id) { detail in
                            Text(detail.rawValue).tag(detail)
                        }
                    }
                    .frame(width: geometry.size.width/3, height: 150, alignment: .center)
                    .clipped( )
                }
            }
            
            Button("Show Detail View") {
                showDetailView = true
            }
            
            NavigationLink("", destination: SomeDetailView(
                selectedHypoHyper: $selectedHypoHyper,
                selectedLyte: $selectedLyte,
                selectedDetail: $selectedDetail), isActive: $showDetailView)
        }
    }
}

struct SomeDetailView: View {
    @Binding var selectedHypoHyper: HypoHyper
    @Binding var selectedLyte: Lytes
    @Binding var selectedDetail: Details
    
    var body: some View {
        // here determine which view you want to show based on the selections, eg a switch(...) {..}
        Text("selectedHypoHyper: \(selectedHypoHyper.rawValue)")
        Text("selectedLyte: \(selectedLyte.rawValue)")
        Text("selectedDetail: \(selectedDetail.rawValue)")
    }
}

Upvotes: 1

Related Questions