Using enum for multiple picker views
#10 - How to change options in a picker based on another picker choice
Hello SwiftUI enthusiast,
Welcome back to Learning SwiftUI! This is issue number 10, I didn't think I would make it this far, but here we are. Writing about SwiftUI has so far been educational for me so I intend to continue with it for a long time. Hope you find this newsletter just as valuable as I do. If you have any improvement suggestions or if you want me to write about a specific topic, just let me know. I am always up for learning new things.
I started working on an app some weeks ago. Alright, alright hold your horses, progress is still slowly going forward. The purpose for the app is to track sport bets. And at the moment I am spending a lot of time on where to position views and so on, it is just so much fun that I can’t help myself. Anyhow, that is not what this issue will be about, in this issue we will take a journey and learn more about enums.
Early on with this app, I encountered some problems when it came to changing the options in a picker view based on what the user selected in another picker. For this case, in the first picker you should select a league, and based on which league you select, the second picker should only display the teams in that particular league. First I thought about using if statements but decided that enums might be the way to go. So in this issue I will go through my learnings setting this up. As I have never used enums before.
This is what we will build today:
https://twitter.com/swiftui_newbie/status/1649453412713463822?s=61&t=wFNWB5ItsvOcPhFA3Jv9Fg
We will start by setting up the enum that we want. It will look like this:
enum Leagues: String, CaseIterable {
case chooseleague = "Choose League"
case laLiga = "LaLiga"
case premierLeague = "Premier League"
case bundesliga = "Bundesliga"
var localName: LocalizedStringKey { LocalizedStringKey(rawValue)}
}
In this case we set up an enum case for three different leagues and one placeholder case for when we have not yet made a selection in the app. We also need to create a LocalizedStringKey variable so our strings can be matched in the first picker.
Next step is to set up a function that can switch the cases in the enum to the teams we want to display for each league. I will not add all teams available for each league in this example, I also added the same “Select Team” string for all cases to be shown when no selection has been made yet.
func selectLeague(league: Leagues) -> [String] {
switch league {
case .chooseleague:
return ["Select Team"]
case .laLiga:
return ["Select Team", "Real Madrid", "Villarreal"]
case .premierLeague:
return ["Select Team", "Arsenal", "Chelsea"]
case .bundesliga:
return ["Select Team", "Bayern Munchen", "Hertha Berlin"]
}
}
The selectLeague function initializes the Leagues enum that we have set up and it returns an array of strings. So as you can see, I’ve only added a few teams, but you can add as many as you want.
When we now have set our enum and function it is time to build the view. Let’s start with this:
struct EnumsForEachExample: View {
@State var chooseLeague: Leagues = .chooseleague
var body: some View {
VStack {
Form {
Picker("Choose League", selection: $chooseLeague) {
ForEach(Leagues.allCases, id: \.self) { league in
Text(league.localName)
}
}
}
}
}
}
Want to learn more about SwiftUI animations?
I created a book for anyone new to SwiftUI that wants to develop their SwiftUI animation skills. The book cover the basics and more advance techniques to animating objects and views in SwiftUI. You can check it out by clicking the link below:
Learning SwiftUI Animations - The Beginner Roadtrip
Two minor examples from the book:
First we set up a state property wrapper that calls our Leagues enum, we have set it to .chooseLeague as default when the view loads.
Next we set up a picker view that binds with chooseLeague, and then we call all cases from the Leagues enum in the ForEach initializer. We also need to call localName to match our case strings. Your view should look like this now:
Our leagues should be visible in the picker view now. Next we will add two more pickers so we can select a home team and away team. For that we need to add two more state property wrappers.
struct EnumsForEachExample: View {
@State var chooseLeague: Leagues = .chooseleague
@State var homeTeam: String = ""
@State var awayTeam: String = ""
var body: some View {
VStack {
Form {
Picker("Choose League", selection: $chooseLeague) {
ForEach(Leagues.allCases, id: \.self) { league in
Text(league.localName)
}
}
Picker("Home Team", selection: $homeTeam) {
ForEach(selectLeague(league: chooseLeague), id: \.self) { selectedHomeTeam in
Text(selectedHomeTeam)
}
}
Picker("Away Team", selection: $awayTeam) {
ForEach(selectLeague(league: chooseLeague), id: \.self) { selectedAwayTeam in
Text(selectedAwayTeam)
}
}
}
}
}
}
Now we have added two more state property wrappers, one for the home team and one for the away team. So now if you test out the pickers, you should see that the content in the home and away team updates depending on what league we choose in the first picker.
What we can do now is to present our selected teams in a view. This is just an example, you can design it however you want.
struct EnumsForEachExample: View {
@State var chooseLeague: Leagues = .chooseleague
@State var homeTeam: String = ""
@State var awayTeam: String = ""
var body: some View {
VStack {
Form {
Picker("Choose League", selection: $chooseLeague) {
ForEach(Leagues.allCases, id: \.self) { league in
Text(league.localName)
}
}
Picker("Home Team", selection: $homeTeam) {
ForEach(selectLeague(league: chooseLeague), id: \.self) { selectedHomeTeam in
Text(selectedHomeTeam)
}
}
Picker("Away Team", selection: $awayTeam) {
ForEach(selectLeague(league: chooseLeague), id: \.self) { selectedAwayTeam in
Text(selectedAwayTeam)
}
}
}
.frame(height: 300)
Spacer()
HStack {
Text(homeTeam)
Text("vs")
Text(awayTeam)
}
.font(.title)
.padding(.horizontal, 20)
.background(
Color.blue
.frame(maxWidth: .infinity)
.frame(height: 50)
.cornerRadius(10)
.opacity(0.5)
)
Spacer()
}
}
}
That was it for this week's issue, this was my first time using enums and I must admit, I really like it. Planning on expanding my knowledge in this area.
On a final note, I am trying to launch a website for Learning SwiftUI, so I would kindly like to to head over to Learning SwiftUI and check it out. I would really appreciate it.
Any feedback is welcome as I am trying to learn the ropes when it comes to Wordpress and web design.
Have a nice day!
Mr SwiftUI