Updated for Xcode 14.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, and it’s usually significantly faster than using a simple @State
as well.
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("niagara-falls")
.offset(dragAmount)
Finally, we would attach a gesture that is bound to our dragAmount
property, like this:
Image("niagara-falls")
.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:
DragGesture().updating()
code creates a new drag gesture, asking it to modify the value stored in dragAmount
– that’s our CGSize
.value
, state
, and transaction
.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.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
.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.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.
SAVE 50% To celebrate WWDC23, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.
Link copied to your pasteboard.