NEW: Join my free 100 Days of SwiftUI challenge today! >>

What is the @GestureState property wrapper?

Paul Hudson    @twostraws   

Fully updated for Xcode 11.2

SwiftUI gives us a specific property wrapper for tracking the state of gestures, helpfully called @GestureState. Although you can accomplish the same using a simple @State property wrapper, @GestureState comes with the added ability that it automatically sets your property back to its initial value when the gesture ends.

For example, we might want to create a gesture that can drag views around. To do that, we’d first need to create an @GestureState property to store how much the view has been moved, like this:

@GestureState var dragAmount = CGSize.zero

That has the default value of CGSize.zero, which means when the gesture ends it will return to that value automatically.

Next, we would attach an offset() modifier so that our view gets moved around by whatever value is in dragAmount:

Image("example-image")
    .offset(dragAmount)

Finally, we would attach a gesture that is bound to our dragAmount property, like this:

Image("example-image")
    .offset(dragAmount)
    .gesture(
        DragGesture().updating($dragAmount) { value, state, transaction in
            state = value.translation
        }
    )

There’s quite a lot of code in there, so let’s unpack it:

  1. The DragGesture().updating() code creates a new drag gesture, asking it to modify the value stored in dragAmount – that’s our CGSize.
  2. It takes a closure with three parameters: value, state, and transaction.
  3. The value parameter is the current data for the drag – where it started, how far it’s moved, where it’s predicted to end, and so on.
  4. The state parameter is an inout value that is our property. So, rather than reading or writing dragAmount directly, inside this closure we should modify state.
  5. The transaction parameter is an inout value that stores the whole animation context, giving us a little information about what’s going on such as whether this is a continuous or transient animation. Continuous animations might be produced by dragging a slider, whereas transient animations might be produced by tapping a button.
  6. To make our view draggable, all we do is assign the current translation the drag straight to state (which is really dragAmount in this case), which in turn is used in the offset() modifier to move the view.

Remember, one of the advantages of @GestureState is that it automatically sets the value of your property back to its initial value when the gesture ends. In this case, it means we can drag a view around all we want, and as soon as we let go it will snap back to its original position.

SPONSORED Instabug helps you identify and resolve severe crashes quickly. You can retrace in-app events and know exactly which line of code caused the crash along with environment details, network logs, repro steps, and the session profiler. Ask more questions or keep users up-to-date with in-app replies straight from your dashboard. Instabug takes data privacy seriously, so no one sees your data but you! See more detailed features comparison and try Instabug's crash reporting SDK for free.

Similar solutions…

BUY OUR BOOKS
Buy Pro Swift Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift (Vapor Edition) Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Server-Side Swift (Kitura Edition) Buy Beyond Code

Was this page useful? Let us know!

Average rating: 5.0/5