💭 Differences Between @GestureState and @State in SwiftUI

Get weekly handpicked updates on Swift and SwiftUI!

TL;DR: @GestureState is ideal for transient gesture-related states, resetting automatically when gestures are interrupted. @State is more versatile but requires manual handling of gesture interruptions.

Background

@GestureState is a dedicated state management tool in SwiftUI designed for gesture operations. In many cases, developers may find that @State can achieve similar functionality. Why, then, did Apple introduce @GestureState? This article compares the two, exploring their use cases and core differences.

Similar Behavior

Both @GestureState and @State can be used to store and update states, such as implementing interactions like tapping or dragging.

Using @GestureState

The following code demonstrates the use of @GestureState:

Swift
struct ContentView: View {
    @GestureState var isPressed = false
    var body: some View {
        Rectangle()
            .fill(.orange)
            .frame(width: 200, height: 200)
            .gesture(
                DragGesture(minimumDistance: 0)
                    .updating($isPressed) { _, state, _ in
                        state = true
                    }
            )
            .overlay(
                Text(isPressed ? "Pressing" : "")
            )
    }
}

In this example, @GestureState is updated to true during the gesture activity and automatically resets to false when the gesture ends or is interrupted.

Using @State

Similar functionality can be achieved with @State:

Swift
struct ContentView: View {
    @State var isPressed = false
    var body: some View {
        Rectangle()
            .fill(.orange)
            .frame(width: 200, height: 200)
            .gesture(
                DragGesture(minimumDistance: 0)
                    .onChanged { _ in
                        isPressed = true
                    }
                    .onEnded { _ in
                        isPressed = false
                    }
            )
            .overlay(
                Text(isPressed ? "Pressing" : "")
            )
    }
}

On the surface, these two approaches appear almost identical in functionality.

Core Differences

Handling gesture interruptions is the key difference between @GestureState and @State.

Gesture Interruption Scenarios

When a gesture is interrupted by a system action (e.g., pulling down the Notification Center or triggering the app switcher gesture without completing it), the onEnded closure will be skipped, leaving the @State reset logic unexecuted. In contrast, @GestureState automatically resets in such cases.

  • Behavior of @GestureState: The state resets to its initial value when the gesture is interrupted, requiring no additional handling.
  • Behavior of @State: The state does not reset upon gesture interruption, retaining its last value and potentially leading to inaccurate state.

Comparison Example

The following video demonstrates the behavioral differences during gesture interruptions:

  • @GestureState: Automatically resets after an interruption.
  • @State: Does not reset automatically, requiring manual interruption handling.

Developers can also leverage the fact that @State does not reset automatically during interruptions to achieve certain special requirements.

Summary of @GestureState Features

  • Designed specifically for gestures, with automated state management.
  • Better suited for transient, gesture-related states.
  • Handles interruptions and resets automatically.
  • Simplifies the setup of animations.

Further Reading