TL;DR: SwiftUI does not natively support multi-finger taps, but you can implement them using UIKit integrations. For iOS 18+, leverage
UIGestureRecognizerRepresentable
to bridge UIKit gestures into SwiftUI. For earlier iOS versions, useUIViewRepresentable
to wrapUITapGestureRecognizer
for multi-finger tap detection.
Background
SwiftUI’s built-in TapGesture
supports only single-finger taps and the number of consecutive taps but does not natively handle multi-finger taps. This guide provides solutions for implementing multi-finger tap gestures across different iOS versions.
iOS 18+
Starting in iOS 18, developers can use UIGestureRecognizerRepresentable
to bridge UIKit gesture recognizers into SwiftUI, enabling multi-finger taps with ease.
Example Code
struct TwoFingerTapDemo: View {
var body: some View {
Rectangle()
.foregroundStyle(.orange)
.frame(width: 200, height: 200)
.onTapGesture {
print("Single Finger Tap")
}
// Apply TwoFingerTapGesture
.gesture(TwoFingerTapGesture {
print("Two-Finger Tap")
})
}
}
struct TwoFingerTapGesture: UIGestureRecognizerRepresentable {
let action: () -> Void
func makeUIGestureRecognizer(context: Context) -> some UIGestureRecognizer {
let gesture = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleGesture))
gesture.numberOfTouchesRequired = 2 // Set required number of fingers
gesture.delegate = context.coordinator
return gesture
}
func makeCoordinator(converter: CoordinateSpaceConverter) -> Coordinator {
Coordinator(action: action)
}
class Coordinator: NSObject, UIGestureRecognizerDelegate {
let action: () -> Void
init(action: @escaping () -> Void) {
self.action = action
}
@objc func handleGesture() {
action()
}
func gestureRecognizer(_: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith _: UIGestureRecognizer) -> Bool {
true // Allow simultaneous gestures
}
}
}
Features
- Custom Gestures:
UIGestureRecognizerRepresentable
allows the seamless integration of UIKit gesture recognizers into SwiftUI. - Advanced Control:
Coordinator
provides hooks for managing gesture behavior, like simultaneous gesture recognition.
Supporting Older iOS Versions
For iOS versions below 18, implement multi-finger taps using UIViewRepresentable
to wrap UIKit gestures in a SwiftUI-compatible component.
Steps to Implement
- Create a UIView for Multi-Finger Tap
A custom
UIView
class with aUITapGestureRecognizer
detects multi-finger taps. - Wrap with UIViewRepresentable
Expose the custom
UIView
as a SwiftUI view. - Extend SwiftUI Add a modifier for easier usage.
Example Code
struct TowFingerTapDemo: View {
var body: some View {
Rectangle()
.foregroundStyle(.orange)
.frame(width: 200, height: 200)
.onTwoFingerTap {
print("Two Touches")
}
.onTapGesture {
print("One Touch")
}
}
}
extension View {
func onTwoFingerTap(perform action: @escaping () -> Void) -> some View {
overlay(TwoFingerTapLayer(action: action))
}
}
struct TwoFingerTapLayer: UIViewRepresentable {
let action: () -> Void
func makeUIView(context: Context) -> some UIView {
let view = TwoFingerTapUIView(action: action)
view.backgroundColor = .clear
return view
}
func updateUIView(_ uiView: Self.UIViewType, context: Self.Context) {}
}
class TwoFingerTapUIView: UIView {
let action: () -> Void
private var gesture: UITapGestureRecognizer!
init(action: @escaping () -> Void) {
self.action = action
super.init(frame: .zero)
setupGesture()
}
@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupGesture() {
gesture = UITapGestureRecognizer(target: self, action: #selector(handleGesture))
gesture.numberOfTouchesRequired = 2 // Set required number of fingers
addGestureRecognizer(gesture)
}
@objc private func handleGesture() {
action()
}
}
Key Points
-
Gesture Order Matters To avoid conflicts, apply custom gestures like
onTwoFingerTap
before SwiftUI’s native gestures:Swift// Correct order .onTwoFingerTap { print("Two-Finger Tap") } .onTapGesture { print("Single Finger Tap") }