How do you use a switch statement with a nested enum?
I'm adding a more general answer for a few reasons.
- This is the only open question regarding nested enums and switch statements. The other one is sadly closed.
- The only legit answer does not show how to assign the value of a nested enum to a symbol. The syntax was not intuitive to me.
- None of the other answers have extensive case examples.
- An enum nested 3 levels deep is more illustrative of the required syntax. Using efremidze answer still took me a while to work it out.
enum Action {
case fighter(F)
case weapon(W)
enum F {
case attack(A)
case defend(D)
case hurt(H)
enum A {
case fail
case success
}
enum D {
case fail
case success
}
enum H {
case none
case some
}
}
enum W {
case swing
case back
}
}
// Matches "3 deep"
let action = Action.fighter(.attack(.fail))
// Matches "1 deep" because more general case listed first.
let action2 = Action.weapon(.swing)
switch action {
case .fighter(.attack(.fail)):
print("3 deep")
case .weapon:
print("1 deep")
case .weapon(.swing):
print("2 deep to case")
case .fighter(.attack):
print("2 deep to another enum level")
default:
print("WTF enum")
}
Swift: Nested enum with switch statement
Your approach will work, you just have a few issues with your implementation. Whether or not this approach is the best way is a different issue which would depend on your requirements. I would switch to an enum with associated values for the parent if possible.
Your
Nested1
enum case can't have the same name as yourNested1
enum. Enum cases should start with a lowercase letter anyway so this is easy to fix.Cases for an enum with an
Int
raw value start at 0 by default but you want your first case to map to 1, so you need to explicitly state that.Initializing an enum with a raw value returns an optional, so you should unwrap that optional before switching on it.
Fixing these issues should give you this, which prints "Helmet" and "Iron":
enum Parent: Int {
enum Nested1: Int {
case bow = 1
case sword
case lance
case dagger
}
enum Nested2: Int {
case wooden = 1
case iron
case diamond
}
case nested1 = 1
case nested2
case case3
case case4
case case5
}
let parent = 2
let nested = 2
guard let parentCase = Parent(rawValue: parent) else {
// Do something to handle invalid enum case here
fatalError()
}
switch parentCase {
case .nested1:
print("Weapon")
case .nested2:
print("Helmet")
guard let nestedCase = Parent.Nested2(rawValue: nested) else {
// Do something to handle invalid enum case here
break
}
switch nestedCase {
case .wooden:
print("Weapon")
case .iron:
print("Iron")
case .diamond:
print("Diamond")
default:
print("")
}
default:
print("")
}
More concise way to nest enums for access by switch statements in Swift?
I think this would be much more concisely expressed with two enums and a tuple. Try this in a playground:
enum HorizontalPosition {
case Left
case Right
case Center
}
enum VerticalPosition {
case Top
case Bottom
case Center
}
typealias Location = (horizontal: HorizontalPosition, vertical: VerticalPosition)
let aLocation = Location(horizontal: .Left, vertical: .Bottom)
switch aLocation {
case (.Left, .Bottom): print ("left bottom")
case (.Center, .Center): print ("center center")
default: print ("everything else")
}
Using Switch Statement with Struct with Nested Enum - Swift
You cannot do pattern matching in the where-clause, but
you could switch on both properties of both cards instead:
switch (card.suit, card.rank, nextCard.suit, nextCard.rank) {
case (.Diamonds, .Num(5), _, .Ace):
count += 100
case (.Hearts, _, _, .Num(let n)) where n >= 3 && n % 2 != 0:
// Or: ... where [3, 5, 7, 9].contains(n):
count += n * 2
default:
break
}
Remark: According to the current Swift API Design Guidelines, enum properties should be lowercase:
Names of types and protocols are
UpperCamelCase
. Everything else islowerCamelCase
.
How to access second-level nested enum passed as parameter in Swift
You would need a giant switch statement to extract the cut styles,
for ingredient in salad {
let cutStyle: CutStyle?
switch ingredient {
case .lettuce(let cut):
cutStyle = cut
case .tomatoes(let cut):
cutStyle = cut
case .onions(let cut):
cutStyle = cut
case .cucumbers(let cut):
cutStyle = cut
case .dressing:
cutStyle = nil
}
print(cutStyle)
}
I think you could have modelled your salad better. Here are two alternative designs that allows you to access the cut style more easily.
One way is to make a SaladIngredient
struct that composes a cut style and an ingredient:
struct SaladIngredient {
enum Ingredient {
case lettuce
case tomatoes
case onions
case cucumbers
case dressing
}
enum CutStyle {
case diced
case chopped
case minced
case grated
}
let ingredient: Ingredient
let cutStyle: CutStyle?
}
func shareSalad(my salad: [SaladIngredient]) {
print("My salad contains:")
for ingredient in salad {
if let cutStyle = ingredient.cutStyle {
print(cutStyle)
}
}
}
The disadvantage of this is that it's harder to enforce the rule that dressings don't have a cut style.
Alternatively, collapse all those enum cases with a cut style into one case:
enum SaladIngredient {
enum Ingredient {
case lettuce
case tomatoes
case onions
case cucumbers
}
enum CutStyle {
case diced
case chopped
case minced
case grated
}
case cuttable(Ingredient, cutStyle: CutStyle)
case dressing
}
func shareSalad(my salad: [SaladIngredient]) {
print("My salad contains:")
for ingredient in salad {
if case .cuttable(_, cutStyle: let cutStyle) = ingredient {
print(cutStyle)
}
}
}
The disadvantage of this is that you are making .dressing
a totally different "type" of thing from lettuce, tomatoes and others.
Using enum type in a switch statement
No case
labels. You've got goto
labels now. Try:
switch(check){
case NEG_INF: printf("neg inf"); return 1;
case ZERO: printf("zero"); return 2;
case POS_INF: printf("pos inf"); return 3;
default: printf("not special"); break;
}
How to use an object which was given from an enum in a switch statement?
You need to declare names to bind the associated properties to instead of using _
.
class ClassOne {
func something() {
print("Hello, world")
}
}
class ClassTwo {
func something2() {
print("Hello, world (2)")
}
}
enum Objects {
case classOne(ClassOne)
case classTwo(ClassTwo)
}
func loadClass(load: Objects) {
switch load {
case .classOne(let classOne): //can also be written: case let .classOne(classOne):
classOne.something()
case .classTwo(let classTwo):
classTwo.something2()
}
}
Note how I've also used the standard Swift naming convention of starting type names with capital letters and property/variable/member names with lowercase letters.
Java using enum with switch statement
The part you're missing is converting from the integer to the type-safe enum. Java will not do it automatically. There's a couple of ways you can go about this:
- Use a list of static final ints rather than a type-safe enum and switch on the int value you receive (this is the pre-Java 5 approach)
- Switch on either a specified id value (as described by heneryville) or the ordinal value of the enum values; i.e.
guideView.GUIDE_VIEW_SEVEN_DAY.ordinal()
Determine the enum value represented by the int value and then switch on the enum value.
enum GuideView {
SEVEN_DAY,
NOW_SHOWING,
ALL_TIMESLOTS
}
// Working on the assumption that your int value is
// the ordinal value of the items in your enum
public void onClick(DialogInterface dialog, int which) {
// do your own bounds checking
GuideView whichView = GuideView.values()[which];
switch (whichView) {
case SEVEN_DAY:
...
break;
case NOW_SHOWING:
...
break;
}
}You may find it more helpful / less error prone to write a custom
valueOf
implementation that takes your integer values as an argument to resolve the appropriate enum value and lets you centralize your bounds checking.
Related Topics
Why Can't I Use 'Type' as the Name of an Enum Embedded in a Struct
Unexpectedly Found Nil While Unwrapping an Optional Value While Reading from Ds with Fromcstring
Is There a Neat Way to Represent a Fraction as an Attributed String
How to Pass Arguments into a Function with Completion Swift
How to Sort an Array of Posts by Their Elements
Where to Place App Delegate Code in App.Swift File
Presenting a Uiviewcontroller from Skscene Shows Black Screen
With Data (Not Nsdata), in Fact How Actually Do You Make a Utf8 Version of a Jpeg
Swift: Download Image from Internet and Cache Them Doesn't Work Properly. Need Suggestions
Swiftui How to Invoke the Function and Change View from Other Page
Access Enum Associated Value as Optional
Swift Catch Enum Case with Binding
Alamofire 5 Escaping Forward Slashes
Which Measuring Unit Is Used in Scnvector3 Position for X, Y and Z in Arkit
Swift Cannot Output When Using Nstimer
Swift: Ambiguous Reference to Member 'Map'