import SwiftUI struct TapRecognizerViewModifier: ViewModifier { @State private var singleTapIsTaped: Bool = .init() var tapSensitivity: Double var singleTapAction: () -> Void var doubleTapAction: () -> Void var anyTapAction: () -> Void init( tapSensitivity: Double, singleTapAction: @escaping () -> Void, doubleTapAction: @escaping () -> Void, anyTapAction: @escaping () -> Void ) { self.tapSensitivity = tapSensitivity self.singleTapAction = singleTapAction self.doubleTapAction = doubleTapAction self.anyTapAction = anyTapAction } func body(content: Content) -> some View { content.gesture(simultaneouslyGesture) } private var singleTapGesture: some Gesture { TapGesture(count: 1).onEnded { anyTapAction() singleTapIsTaped = true DispatchQueue.main.asyncAfter(deadline: .now() + tapSensitivity) { if singleTapIsTaped { singleTapAction() } } } } private var doubleTapGesture: some Gesture { TapGesture(count: 2).onEnded { singleTapIsTaped = false doubleTapAction() } } private var simultaneouslyGesture: some Gesture { singleTapGesture.simultaneously(with: doubleTapGesture) } } extension View { func tapRecognizer( tapSensitivity: Double, singleTapAction: @escaping () -> Void, doubleTapAction: @escaping () -> Void, anyTapAction: @escaping () -> Void = {} ) -> some View { modifier( TapRecognizerViewModifier( tapSensitivity: tapSensitivity, singleTapAction: singleTapAction, doubleTapAction: doubleTapAction, anyTapAction: anyTapAction ) ) } }