Nested enums with associated values misbehave as @State variables in SwiftUI

When using an enum with associated values as an associated value of another enum, something weird happens in SwiftUI - the outer enum inexplicably changes to a different case:

enum Value {
    case whole(Number)
    case fraction(Number, Number)
}

enum Number {
    case int(Int)
    case double(Double)
}

struct ContentView: View {
   @State var value: Value = .fraction(.int(1), .int(1))
    
   var body: some View {
      VStack() {
         Text("\(value)" as String)
            
         Button("randomize denominator") {
            self.value = .fraction(.int(1), .int(Int.random(in: 1...100)))
         }
      }
   }
}

Changing the enum value where the first associated value (the numerator) is kept the same, while changing the second associated value (the denominator), toggles the case of the value between whole and fraction.

Here's what the screen shows (for brevity I'm omitting the CustomStringConvertable of each enum) after each button click:

.fraction(.int(1),.int(64))
.whole(.int(1))
.fraction(.int(1),.int(23))
.whole(.int(1))
.fraction(.int(1),.int(87))

The state variable value inexplicably toggles its case.

This erroneous behavior goes away if:

  1. nested enum has only one case
  2. nested enum doesn't have associated values
  3. first associated value (numerator) also changes
  4. the order of cases whole and fraction is reversed (fraction comes first)

This feels like a bug, but wanted to confirm, because it's not clear what SwiftUI does behind the scenes here. And if it is a bug, is there a way to address it, either by explaining why the reasons above caused it or in some other way?

Terms of Service

Privacy Policy

Cookie Policy