🔋

Disabling Animations in SwiftUI: Instant Transitions for Sheets & NavigationStack

(Updated on )

TL;DR: The standard way to “silently” present a view or push a navigation page (without animation) in SwiftUI is to wrap the state change in withTransaction and set disablesAnimations to true. This is crucial for handling Deep Links or resetting App state.

SwiftUI provides built-in transition animations for many components (such as Sheet, FullScreenCover, and NavigationStack) by default. However, in certain scenarios—such as Deep Link navigation or jumping directly to a specific page after a launch screen—developers need to bypass these visual transitions and enter the target state immediately.

The Principle

While SwiftUI doesn’t provide a direct animated: false modifier parameter like UIKit did, we can leverage the Transaction mechanism. By customizing a Transaction and setting its disablesAnimations property to true, we can force SwiftUI to ignore all implicit and explicit animations triggered by that specific state change.

Core Logic

Swift
var transaction = Transaction(animation: .none)
transaction.disablesAnimations = true

withTransaction(transaction) {
    // State change code triggering Sheet or Navigation
    isActive = true 
}

Practical Examples

1. Disabling Sheet Animations

This is particularly useful when you need to swap out view hierarchies or present a modal instantly upon a trigger.

Swift
struct SheetDemo: View {
    @State private var isActive = false
    
    var body: some View {
        Button("Present Immediately (No Animation)") {
            var transaction = Transaction(animation: .none)
            transaction.disablesAnimations = true
            
            withTransaction(transaction) {
                isActive = true
            }
        }
        .sheet(isPresented: $isActive) {
            SheetContent(isActive: $isActive)
        }
    }
}

struct SheetContent: View {
    @Binding var isActive: Bool
    
    var body: some View {
        VStack {
            Text("Sheet View")
            Button("Dismiss Immediately (No Animation)") {
                var transaction = Transaction(animation: .none)
                transaction.disablesAnimations = true
                
                withTransaction(transaction) {
                    isActive = false
                }
            }
        }
    }
}

Demo

Disable Sheet Animation Demo

2. Disabling NavigationStack Transitions

In the era of iOS 17+ and Swift 6, NavigationStack combined with @Observable is the mainstream approach for data-driven navigation. Here is how to push a new page silently:

Swift
@Observable
class PathStore {
    var path: [Int] = []
}

struct NavigationStackDemo: View {
    @State var pathStore = PathStore()
    
    var body: some View {
        NavigationStack(path: $pathStore.path) {
            List {
                Button("Push Page (No Animation)") {
                    var transaction = Transaction(animation: .none)
                    transaction.disablesAnimations = true
                    
                    withTransaction(transaction) {
                        pathStore.path.append(1)
                    }
                }
            }
            .navigationDestination(for: Int.self) { n in
                Text("Page \(n)")
            }
        }
    }
}

Demo

Disable NavigationStack Animation Demo

Key Considerations

  1. Scope Limitation: The Transaction settings only affect state changes that occur inside the withTransaction closure. If you accidentally include unrelated state changes (like a color toggle) within the closure, their animations will also be disabled.

  2. Avoid Side Effects: It is recommended to isolate the state change logic used for navigation. Do not mix it with general business logic to ensure disablesAnimations doesn’t inadvertently kill animations for other UI components.

  3. Compatibility: This method remains effective and stable in the latest versions of SwiftUI and is considered best practice for Deep Link scenarios.

Further Reading

Related Tips

Subscribe to Fatbobman

Weekly Swift & SwiftUI highlights. Join developers.

Subscribe Now