SwiftUI nos proporciona un property wrapper específico para hacer un tracking del estado de los gestos llamado @GestureState. Si bien un contenedor de propiedad @State básico puede hacer lo mismo, @GestureState tiene la ventaja de devolver inmediatamente la propiedad a su valor inicial al final del gesto. También suele ser mucho más rápido que usar un @State simple.
Para poder hacer un tracking del estado de los gestos usamos @GestureState. Imaginate que queremos distinguir entre un evento tap y un evento que sea un tap largo. ¿Como los diferenciamos?
SwiftUI proporciona este property wrapper que convenientemente rastrea el cambio de estado de un gesto y permite a los desarrolladores decidir la acción correspondiente a hacer.
Por ejemplo, imagina que queremos implementar una animación en la cual queremos oscurecer un poco la imagen cuando el usuario haga tap y también la queremos redimensionar cuando haya un tap largo. Durante el desempeño del gesto de pulsación prolongada, tenemos que diferenciar entre tap y tap de pulsación prolongada y esto lo podemos hacer con el property wrapper @GestureState.
Por lo que vamos a empezar declarando nuestro @GestureState de la siguiente forma:
@GestureState private var longPressTap = falseEste estado de gesto indica si un tap es detectado durante durante la realizacion del gesto de pulsación larga.
A continuación podemos ver como sigue el ejemplo:
@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()
})
)
}Con el modifier .opacity cuando un tap es detectado ponemos la opacidad a 0.5 haciendo que la imagen se vuelva más tenue.
Ahora vamos a explicar el método updating de LongPressGesture. Durante la realización del gesto de pulsación prolongada, este método será llamado. Acepta tres parámetros: value, state y transaction.
El parámetro value es el estado actual del gesto. Este valor varia de gesto a gesto, pero para el gesto de pulsación prolongada, un valor true indica que un tap ha sido detectado.
El parámetro state es en realidad un parámetro de entrada y salida que permite actualizar el valor de la propiedad longPressTap. En el código anterior, configuramos el valor de estado en currentState. En otras palabras, la propiedad longPressTap siempre realiza un seguimiento del útlimo estado del gesto de pulsación prolongada.
El parámetro transaction almacena el contexto de la actualización de procesamiento de estado actual.
Este sería el resultado en XCode:

Como se puede apreciar la imagen aparece más tenue una vez se detecta un tap por parte del usuario. Si se mantiene presionada por más de un segundo, la imagen se redimensiona. La opacidad de la imagen es automaticamente reseteada a normal cuando el usuario deja de hacer la pulsación larga. Gracias a @GestureState, cuando el gesto termina, automáticamente pone el valor de la propiedad estado de gesto a su valor inicial, false en nuestro caso.










