Skip to content

Instantly share code, notes, and snippets.

@aheze
Last active December 14, 2020 20:53
Show Gist options
  • Save aheze/3d5820c03616d25e21376ad561798e9e to your computer and use it in GitHub Desktop.
Save aheze/3d5820c03616d25e21376ad561798e9e to your computer and use it in GitHub Desktop.
/// iOS 13 version here: https://gist.github.com/aheze/bd4e1990dbeda66e60c00c6341451930
/// Note: iOS 13 version has a "bug" where adding a second finger freezes the touch event
/// More details here: https://developer.apple.com/forums/thread/660070
/// Thanks @brentbrinkley for discovering the bug!
/// if you're on iPad Swift Playgrounds and you put all of this code in a seperate file,
/// you need to make everything public so that the compiler detects it.
/// the possible states of the button
public enum ButtonState {
case pressed
case notPressed
}
/// ViewModifier allows us to get a view, then modify it and return it
public struct TouchDownUpEventModifier: ViewModifier {
/// Properties marked with `@GestureState` automatically resets when the gesture ends/is cancelled
/// for example, once the finger lifts up, this will reset to false
/// this functionality is handled inside the `.updating` modifier
@GestureState private var isPressed = false
/// this is the closure that will get passed around.
/// we will update the ButtonState every time your finger touches down or up.
let changeState: (ButtonState) -> Void
/// a required function for ViewModifier.
/// content is the body content of the caller view
public func body(content: Content) -> some View {
/// declare the drag gesture
let drag = DragGesture(minimumDistance: 0)
/// this is called whenever the gesture is happening
/// because we do this on a `DragGesture`, this is called when the finger is down
.updating($isPressed) { (value, gestureState, transaction) in
/// setting the gestureState will automatically set `$isPressed`
gestureState = true
}
return content
.gesture(drag) /// add the gesture
.onChange(of: isPressed, perform: { (pressed) in /// call `changeState` whenever the state changes
/// `onChange` is available in iOS 14 and higher.
if pressed {
self.changeState(.pressed)
} else {
self.changeState(.notPressed)
}
})
}
/// if you're on iPad Swift Playgrounds and you put all of this code in a seperate file,
/// you need to add a public init so that the compiler detects it.
public init(changeState: @escaping (ButtonState) -> Void) {
self.changeState = changeState
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment