BLACK FRIDAY SALE: Save big on all my Swift books and bundles! >>

Help with Pickers

Forums > SwiftUI

So, I have been refactoring my views, which took a bit to get used to.. Now I have a view that is for Attendance, I have a picker and an enum. What I would like to do, is to be able to select the period of the class being taught, and the cooresponding class being taught, i.e firstPeriod be shown. I think that I would need to keep the picker in the Attendance view, and once the user selects the class period. The selectedPeriod is sent to the roster.swift file where the students in firstPeriod are selected and returned as a view. (keeping the sorting and etc. out of the view).

Am I thinking correctly on this?

Thank you.

Bob

See below for my Attendance View.

import SwiftUI

struct Attendance: View {
    @EnvironmentObject var roster: Roster
    @State var selectedPeriod = Period.firstPeriod

    enum Period: String, CaseIterable, Identifiable {
        var id: String {self.rawValue}
        case firstPeriod
        case secondPeriod
        case thirdPeriod
        case fourthPeriod
        case fifthPeriod
        case sixthPeriod
        case seventhPeriod
        case eighthPeriod
        case flexPeriod
    }
    var body: some View {
        NavigationView {
            Form {
                Section(header: Text("Select Period")) {
                    Section {
                        Picker("Select Period", selection: $selectedPeriod) {
                            Text("1st").tag(Period.firstPeriod)
                            Text("2nd").tag(Period.secondPeriod)
                            Text("3rd").tag(Period.thirdPeriod)
                            Text("4th").tag(Period.fourthPeriod)
                            Text("5th").tag(Period.fifthPeriod)
                            Text("6th").tag(Period.sixthPeriod)
                            Text("7th").tag(Period.seventhPeriod)
                            Text("8th").tag(Period.eighthPeriod)
                            Text("Flex").tag(Period.flexPeriod)
                        }
                        .pickerStyle(.segmented)
                    }
                }
                Section(header: Text("Period Roster")) {
                    roster.attendance()
                }
            }
        }
        .navigationTitle("Attendance")
        .navigationBarTitleDisplayMode(.inline)
        .navigationViewStyle(.stack) // Makes the view full width
        .accentColor(.blue)
    }
}
struct Attendance_Previews: PreviewProvider {
    static var previews: some View {
        Attendance()
            .previewInterfaceOrientation(.landscapeLeft)
    }
}

   

Hi blawson3,

There maybe a more efficient way of doing this and I am sure others may provide this however this approach should work for you.

struct RosterView: View {
    // Defines two classes for testing
    private var class1 = [
    "Joe",
    "Tima",
    "Jess"
    ]

    private var class2 = [
    "Taylor",
    "Megan",
    "Olivia",
    "Steph"
    ]

    enum Classes: String {
        case class1
        case class2
    }

    // This it the var where the picker is bound
    @State private var selectedItem = Classes.class1

    // Creates a dictionary of a classess enum to match an array of strings
    private var classToMatch:[Classes:[String]] = [:]

    init() {
        // initialises the classToMatch var with the arrays it requires
        self.classToMatch = [
            Classes.class1: class1,
            Classes.class2: class2
        ]
    }

    var body: some View {
        Picker("Test", selection: $selectedItem) {
            Text("Class 1").tag(Classes.class1)
            Text("Class 2").tag(Classes.class2)
        }

        // Used a force unwrap here as the value should never be nil as it's bound to a picker
        // however you can unwrap if required. What happens here is that the selectedItem is
        // passed to the classToMatch dictionary which then returns all of the students in
        // that array, we then extract one student from the returned array and display it
        // as a text item on the screen.

        ForEach(classToMatch[selectedItem]!, id: \.self) { student in
            Text(student)
        }
    }
}

In order to make this code work for your use case you can swap out Class1 and Class2 in the initialiser for any array of students from your Roster model.

Hope this helps.

   

Thank you, I will need to look closely at this to make sure that I can understand it, (still a beginner).

Thank you!!

Bob

   

I am in learning process but will try My best to learn and do it for my https://www.lifepo4golfcartbattery.com/ business

   

Hacking with Swift is sponsored by RevenueCat

SPONSORED In-app subscriptions are a pain to implement, hard to test, and full of edge cases. RevenueCat makes it straightforward and reliable so you can get back to building your app. Oh, and it's free if your app makes less than $10k/mo.

Learn more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.