Skip to content

Transactions (SwiftUI)

A SwiftUI guide for coding agents. Also covers withtransaction, override child animation, disablesanimations, transaction modifier, animation context state change, gesture animation override.

A Transaction is the context of one state-processing update. SwiftUI creates one for every state change; it carries the animation to apply and a flag that disables animations set by child views. Reach for it when a child view owns its animation and you need to override it.

Override From the Call Site

A leaf view with its own .animation(.spring()) cannot be re-animated from outside through the normal API. withTransaction wraps the mutation in a custom transaction that wins.

AnimatedView(scale: scale ? 0.5 : 1)
  .onTapGesture {
    var transaction = Transaction(animation: .linear)
    transaction.disablesAnimations = true

    withTransaction(transaction) {
      scale.toggle()
    }
  }

disablesAnimations = true turns off every animation declared inside the hierarchy, and the transaction's own animation runs instead.

Per-View Transaction Modifier

The transaction modifier edits the current transaction for one view. Its closure receives the Transaction as inout, so you can swap the animation or kill it for that view only.

VStack {
  AnimatedView(scale: scale ? 0.5 : 1)
    .transaction { $0.animation = .spring() }
  AnimatedView(scale: scale ? 0.5 : 1)
    .transaction { $0.disablesAnimations = true }
}
.onTapGesture { scale.toggle() }

One state change, two behaviors: the first view springs, the second snaps with no animation.

Gestures and Bindings

Gesture updating closures receive the transaction as their third parameter, so a drag can animate its own state updates.

DragGesture()
  .updating($offset) { value, state, transaction in
    state = value.translation
    transaction.animation = .interactiveSpring()
  }

A binding can carry its own transaction too. Every write through the derived binding then runs with that animation context.

private var animatedBinding: Binding<Bool> {
  var transaction = Transaction(animation: .interactiveSpring())
  transaction.disablesAnimations = true
  return $scale.transaction(transaction)
}

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-swiftui-guide({ topic: "swiftui-transactions" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems