I have an ObservableObject
that has a member property with the @GestureState
wrapper. In my View, how do I get access to the GestureState
property?
I've already tried using dot notation with the $
binding to try to expose the GestureState but it doesn't like that
My AppState ObservableObject
:
class AppState: ObservableObject {
let objectWillChange = ObservableObjectPublisher()
@GestureState var currentState: LongPressState = .inactive
public enum LongPressState: String {
case inactive = "inactive"
case pressing = "pressing"
case holding = "holding"
}
}
The implementation of the object in my code:
@ObservedObject var appState: AppState
.
.
.
let longPress = LongPressGesture(minimumDuration: minLongPressDuration)
.sequenced(before: LongPressGesture(minimumDuration: 5))
.updating(appState.$currentState) { value, state, transaction in
switch value {
case .first(true):
state = .pressing
case .second(true, false):
state = .holding
default:
state = .inactive
}
}
I'm actually not getting any buildtime errors in this View but it invalidates the View higher up the hierarchy. If I replace the @ObservedObject
with a local @GestureState
property then it works fine.
I have found a workaround that works perfectly.
The idea is simple: You have your currentState
two times.
GestureState
ObservableObject
class as Published
This is necessary since GestureState
can only be declared within a view. The only thing left to do now is to somehow sync them.
Here is one possible solution: (using onChange(of:)
)
class AppState: ObservableObject {
@Published var currentState: LongPressState = .inactive
enum LongPressState: String { ... }
...
}
struct ContentView: View {
@StateObject private var appState = AppState()
@GestureState private var currentState: AppState.LongPressState = .inactive
var body: some View {
SomeView()
.gesture(
LongPressGesture()
.updating($currentState) { value, state, transaction in
...
}
)
.onChange(of: currentState) { appState.currentState = $0 }
}
}
I have found that the animation was kind of buggy. Adding an onEnded
to the gesture fixed it (DragGesture).
.onEnded {
appState.currentState = .inactive //if you are using DragGesture: .zero (just set to it's initial state again)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With