SwiftUI Switch Statement Transition Behavior is not as expected

585 Views Asked by At

I am getting unexpected .transition behavior when using a switch statement to update the View vs. when using two if statements. The two if statements are sliding the views back in and out as expected, however, the same transitions in the switch statement are causing the views to slide in from one side and exit the other.

I am looking to use the switch syntax to keep my code consistent (as to how I am updating the view) but get the behavior that is commensurate with the if statements.

Here is some example code in which one can observe the Top Rectangles and the Botton Rectangles exhibiting different transition behavior:

import SwiftUI

enum ExampleStep: Int {
    
    case stepOne
    case stepTwo
    
}

struct TransitionExample: View {
    
    @State var exampleStep:ExampleStep = .stepOne
    
    
    var body: some View {
        
        VStack {
            
            Button {
                
                withAnimation {
                    exampleStep = exampleStep == .stepOne ? .stepTwo : .stepOne
                }
            
            } label: {
                Text("Click Me")
            }
            
            Spacer()
            
            if exampleStep == .stepOne {
                
                Rectangle()
                    .foregroundColor(Color.green)
                    .frame(width: 100, height: 100)
                    .transition(.move(edge: .leading))

            }
            
            if exampleStep == .stepTwo {
                
                Rectangle()
                    .foregroundColor(Color.red)
                    .frame(width: 100, height: 100)
                    .transition(.move(edge: .trailing))
                
            }
            
            Spacer()
            
            switch exampleStep {
                
            case .stepOne:
                Rectangle()
                    .foregroundColor(Color.green)
                    .frame(width: 100, height: 100)
                    .transition(.move(edge: .leading))
                
            case .stepTwo:
                Rectangle()
                    .foregroundColor(Color.red)
                    .frame(width: 100, height: 100)
                    .transition(.move(edge: .trailing))
                
            
            
            }
            
            Spacer()
            
        }
        
    }
    
}

struct TransitionExample_Previews: PreviewProvider {
    static var previews: some View {
        TransitionExample()
    }
}
1

There are 1 best solutions below

1
On BEST ANSWER

The difference likely has to do with how the SwiftUI result builder translates the if statement into buildIf, buildEither, etc vs. how the switch statements are translated. See: https://jasonzurita.com/swiftui-if-statement/

It looks like you can get the behavior to match the if statements if you explicitly define asymmetric transitions in the switch statement:

switch exampleStep {
    
case .stepOne:
    Rectangle()
        .foregroundColor(Color.green)
        .frame(width: 100, height: 100)
        .transition(.asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing)))
    
case .stepTwo:
    Rectangle()
        .foregroundColor(Color.red)
        .frame(width: 100, height: 100)
        .transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)))
    
}