Swift and SwiftUI tutorials for Swift Developers

What is the @GestureState property wrapper

SwiftUI provides us with a specific property wrapper for tracking gesture state called @GestureState. While a basic @State property wrapper can do the same, @GestureState has the advantage of immediately returning the property to its initial value at the end of the gesture. It is also often much faster than using a simple @State.

In order to track gesture state we use @GestureState. Imagine we want to distinguish between a tap event and a long tap event. How do we differentiate them?

SwiftUI provides this property wrapper that conveniently tracks the state change of a gesture and allows developers to decide the corresponding action to take.

For example, imagine we want to implement an animation in which we want to darken the image a bit when the user taps and we also want to resize it when there is a long tap. During the performance of the long tap gesture, we need to differentiate between tap and long tap and we can do this with the @GestureState property wrapper.

So let’s start by declaring our @GestureState like this:

@GestureState private var longPressTap = false

This gesture state indicates whether a tap is detected during the execution of the long press gesture.

Below we can see how the example goes:

@State private var isPressed = false
    var body: some View {
        
        Image(systemName: "macpro.gen3.fill")
            .font(.system(size: 200))
            .opacity(longPressTap ? 0.5 : 1)
            .scaleEffect(isPressed ? 0.5 : 1)
            .animation(.easeInOut, value: isPressed)
            .foregroundStyle(.blue)
            .gesture(
                LongPressGesture(minimumDuration: 1.0)
                    .updating($longPressTap, body: { (currentState, state, transaction) in
                        
                        state = currentState
  
                    })
                    .onEnded({ _ in
                        
                        self.isPressed.toggle()
                        
                    })
                )
    }

With the .opacity modifier when a tap is detected we set the opacity to 0.5 making the image dimmer.

Now let’s explain the updating method of LongPressGesture. During the execution of the long press gesture, this method will be called. It accepts three parameters: value, state and transaction.

The value parameter is the current state of the gesture. This value varies from gesture to gesture, but for the long press gesture, a value of true indicates that a tap has been detected.

The state parameter is actually an input and output parameter that allows updating the value of the longPressTap property. In the code above, we set the state value to currentState. In other words, the longPressTap property always keeps track of the last state of the long press gesture.

The transaction parameter stores the context of the current state processing update.

This would be the result in XCode:

As you can see, the image appears dimmer once a tap is detected by the user. If the tap is held for more than a second, the image is resized. The image opacity is automatically reset to normal when the user stops tapping. Thanks to @GestureState, when the gesture ends, it automatically sets the value of the gesture state property to its initial value, false in our case.

Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Article

What's and how to use LongPressGesture in SwiftUI

Related Posts