Search code examples
xcodeapple-watch

picker to list in Xcode


I am making a school timetable app where you select the day on tab 2 and it shows the day's schedule on the other but I haven't been able to translate the picker choice into which day is shown. I have put the data for each day into private var's Amonday - Afriday and will add b versions (as seen in picker options) later once I have the picker selection working

Xcode 13.3 building for Apple Watch

import SwiftUI

struct Period: Identifiable {
    let name: String
    let id = UUID()
}

private var Amonday = [
    Period(name: "Maths"),
    Period(name: "Break: Library duty"),
    Period(name: "Science"),
    Period(name: "French"),
    Period(name: "Lunch: Library duty"),
    Period(name: "English"),
    Period(name: "Re")
]
private var Atuesday = [
    Period(name: "german"),
    Period(name: "break"),
    Period(name: "history"),
    Period(name: "science"),
    Period(name: "Lunch: Politics club"),
    Period(name: "dt"),
    Period(name: "maths")
]
private var Awednesday = [
    Period(name: "dt"),
    Period(name: "break"),
    Period(name: "german"),
    Period(name: "music"),
    Period(name: "lunch"),
    Period(name: "geography"),
    Period(name: "english")
]
private var Athursday = [
    Period(name: "art"),
    Period(name: "Break"),
    Period(name: "Geography"),
    Period(name: "Pe"),
    Period(name: "Lunch"),
    Period(name: "science"),
    Period(name: "history"),
]
private var Afriday = [
    Period(name: "English"),
    Period(name: "break"),
    Period(name: "Science"),
    Period(name: "Maths"),
    Period(name: "Lunch"),
    Period(name: "Pe"),
    Period(name: "Computeing")
]

var today = Amonday

var selectedday = 1

struct ContentView: View {
    var body: some View {
        TabView(selection: /*@START_MENU_TOKEN@*//*@PLACEHOLDER=Selection@*/.constant(1)/*@END_MENU_TOKEN@*/) {
            List(Amonday) {
                    Text($0.name)
                }
                .tabItem {  }.tag(1)
            
            Picker(selection: /*@START_MENU_TOKEN@*/.constant(1)/*@END_MENU_TOKEN@*/, label: Text("")
                .frame(height: 4.0)) {
                    Text("A - Monday").tag(1)
                    Text("A - Tuesday").tag(2)
                    Text("A - Wednesday").tag(3)
                    Text("A - Thursday").tag(4)
                    Text("A - Friday").tag(5)
                    Text("B - Monday").tag(6)
                    Text("B - Tuesday").tag(7)
                    Text("B - Wednesday").tag(8)
                    Text("B - Thursday").tag(9)
                    Text("B - Friday").tag(10)
                
                }.tabItem {  }.tag(2)
        }
        
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            
    }
}

Solution

  • There are many ways of solving this but one option is to have a variable that stores the day information in the Period

    It seems like in your case the day is made of a schedule type (A and B) and the weekday.

    struct Period: Identifiable {
        let name: String
        //Day for the period
        let day: Day
        let id = UUID()
    }
    //Combine Schdule type with available day
    struct Day: Hashable{
        let weekday: Days
        let schedule: Schedule
    }
    //Possible days
    enum Days: String, CaseIterable, Identifiable{
        var id: String{
            rawValue
        }
        case monday
        case tuesday
        case wednesday
        case thursday
        case friday
    }
    //Schedule types
    enum Schedule: String, CaseIterable, Identifiable{
        var id: String{
            rawValue
        }
        case a
        case b
    }
    

    Once you have the day variable you have the Picker use a Day object as the selection variable.

    And then you can have a filtered list

    private var schedule = [
        Period(name: "Maths", day: .init(weekday: .monday, schedule: .a)),
        Period(name: "Break: Library duty", day: .init(weekday: .monday, schedule: .a)),
        Period(name: "Science", day: .init(weekday: .monday, schedule: .a)),
        Period(name: "French", day: .init(weekday: .monday, schedule: .a)),
        Period(name: "Lunch: Library duty", day: .init(weekday: .monday, schedule: .a)),
        Period(name: "English", day: .init(weekday: .monday, schedule: .a)),
        Period(name: "Re", day: .init(weekday: .monday, schedule: .a)),
        
        Period(name: "german", day: .init(weekday: .tuesday, schedule: .a)),
        Period(name: "break", day: .init(weekday: .tuesday, schedule: .a)),
        Period(name: "history", day: .init(weekday: .tuesday, schedule: .a)),
        Period(name: "science", day: .init(weekday: .tuesday, schedule: .a)),
        Period(name: "Lunch: Politics club", day: .init(weekday: .tuesday, schedule: .a)),
        Period(name: "dt", day: .init(weekday: .tuesday, schedule: .a)),
        Period(name: "maths", day: .init(weekday: .tuesday, schedule: .a)),
        
        Period(name: "dt", day: .init(weekday: .wednesday, schedule: .a)),
        Period(name: "break", day: .init(weekday: .wednesday, schedule: .a)),
        Period(name: "german", day: .init(weekday: .wednesday, schedule: .a)),
        Period(name: "music", day: .init(weekday: .wednesday, schedule: .a)),
        Period(name: "lunch", day: .init(weekday: .wednesday, schedule: .a)),
        Period(name: "geography", day: .init(weekday: .wednesday, schedule: .a)),
        Period(name: "english", day: .init(weekday: .wednesday, schedule: .a)),
        
        Period(name: "art", day: .init(weekday: .thursday, schedule: .a)),
        Period(name: "Break", day: .init(weekday: .thursday, schedule: .a)),
        Period(name: "Geography", day: .init(weekday: .thursday, schedule: .a)),
        Period(name: "Pe", day: .init(weekday: .thursday, schedule: .a)),
        Period(name: "Lunch", day: .init(weekday: .thursday, schedule: .a)),
        Period(name: "science", day: .init(weekday: .thursday, schedule: .a)),
        Period(name: "history", day: .init(weekday: .thursday, schedule: .a)),
        
        Period(name: "English", day: .init(weekday: .friday, schedule: .a)),
        Period(name: "break", day: .init(weekday: .friday, schedule: .a)),
        Period(name: "Science", day: .init(weekday: .friday, schedule: .a)),
        Period(name: "Maths", day: .init(weekday: .friday, schedule: .a)),
        Period(name: "Lunch", day: .init(weekday: .friday, schedule: .a)),
        Period(name: "Pe", day: .init(weekday: .friday, schedule: .a)),
        Period(name: "Computeing", day: .init(weekday: .friday, schedule: .a))
    ]
    struct PeriodView: View {
        //Selected Day for Picker
        @State var selectedday: Day? = nil
        //TabView selection
        @State var selection: Options = .list
        //Contains a filtered list if `selectedday != nil`
        var filteredSchedule: [Period]{
            schedule.filter({ period in
                if let selectedday = selectedday {
                    return period.day.weekday == selectedday.weekday && period.day.schedule == selectedday.schedule
                }else{
                    return true
                }
            })
        }
        var body: some View {
            TabView(selection: $selection) {
                VStack{
                    if let selectedday = selectedday {
                        Text("\(selectedday.schedule.rawValue) - ".capitalized) + Text("\(selectedday.weekday.rawValue)".capitalized)
                    }else{
                        Text("Showing All")
                    }
                    List(filteredSchedule) {
                        Text($0.name)
                    }
                }
                .tabItem {
                    Text("list")
                }.tag(Options.list)
                
                Picker(selection: $selectedday, label: Text("")){
                    Text("All").tag(nil as Day?) //Types must match exactly
                    ForEach(Days.allCases, id:\.id){ dCase in
                        Group{
                            Text("A - ".capitalized) + Text("\(dCase.rawValue)".capitalized)
                        }
                        .tag(Day(weekday: dCase, schedule: .a) as Day?) //Types must match exactly
                        Group{
                            Text("B - ".capitalized) + Text("\(dCase.rawValue)".capitalized)
                        }
                        .tag(Day(weekday: dCase, schedule: .b) as Day?) //Types must match exactly
                    }
                }
                .tabItem {
                    Text("selection")
                }
                .tag(Options.selection)
            }
        }
        enum Options{
            case list
            case selection
        }
    }
    
    struct PeriodView_Previews: PreviewProvider {
        static var previews: some View {
            PeriodView()
        }
    }