UITapGestureRecognizer
iOS Development
Gesture Recognition
Single Tap
Double Tap

UITapGestureRecognizer - single tap and double tap

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Supporting both single and double tap on the same view is a classic iOS gesture coordination problem. If recognizers are configured independently, a double tap can incorrectly trigger single-tap logic first. The correct setup uses explicit failure dependency so the single tap waits for double-tap recognition to fail.

Configure Recognizers With Clear Responsibilities

Create two recognizers, assign different tap counts, and attach both to the same target view.

swift
1import UIKit
2
3final class PhotoViewController: UIViewController {
4    private let imageView = UIImageView()
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8
9        imageView.frame = view.bounds
10        imageView.isUserInteractionEnabled = true
11        imageView.contentMode = .scaleAspectFit
12        imageView.image = UIImage(named: "sample")
13        view.addSubview(imageView)
14
15        let singleTap = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap(_:)))
16        singleTap.numberOfTapsRequired = 1
17
18        let doubleTap = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap(_:)))
19        doubleTap.numberOfTapsRequired = 2
20
21        singleTap.require(toFail: doubleTap)
22
23        imageView.addGestureRecognizer(singleTap)
24        imageView.addGestureRecognizer(doubleTap)
25    }
26
27    @objc private func handleSingleTap(_ gesture: UITapGestureRecognizer) {
28        print("single tap")
29    }
30
31    @objc private func handleDoubleTap(_ gesture: UITapGestureRecognizer) {
32        print("double tap")
33    }
34}

require(toFail:) is the critical line. Without it, tap timing can produce ambiguous behavior.

Keep Handlers Lightweight

Gesture callbacks run on the main thread. Heavy work inside handlers causes stutter and delayed feedback.

Good pattern:

  • Keep UI feedback immediate.
  • Dispatch heavy work to background tasks.
  • Avoid network requests directly from gesture handlers.
swift
1@objc private func handleSingleTap(_ gesture: UITapGestureRecognizer) {
2    UIView.animate(withDuration: 0.12) {
3        self.imageView.alpha = 0.75
4    } completion: { _ in
5        self.imageView.alpha = 1.0
6    }
7
8    print("toggle selection")
9}

This keeps interaction responsive even on older devices.

Manage Gesture Conflicts With Scroll Views

Taps often coexist with panning and zooming. For example, inside a UIScrollView, double tap might zoom while single tap toggles chrome controls. Use gesture delegate methods when default conflict resolution is insufficient.

swift
1final class GalleryController: UIViewController, UIGestureRecognizerDelegate {
2    private let scrollView = UIScrollView()
3    private let imageView = UIImageView()
4
5    override func viewDidLoad() {
6        super.viewDidLoad()
7
8        let singleTap = UITapGestureRecognizer(target: self, action: #selector(toggleChrome))
9        singleTap.numberOfTapsRequired = 1
10
11        let doubleTap = UITapGestureRecognizer(target: self, action: #selector(toggleZoom))
12        doubleTap.numberOfTapsRequired = 2
13        doubleTap.delegate = self
14
15        singleTap.require(toFail: doubleTap)
16
17        imageView.addGestureRecognizer(singleTap)
18        imageView.addGestureRecognizer(doubleTap)
19    }
20
21    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
22                           shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
23        return false
24    }
25
26    @objc private func toggleChrome() {}
27    @objc private func toggleZoom() {}
28}

Most screens should keep this logic simple. Complex simultaneous recognition policies are harder to debug.

Accessibility and UX Considerations

Double tap precision can be difficult for some users. If double tap triggers a critical action, provide a visible alternative control such as a button or menu item. Also verify behavior with larger text and VoiceOver enabled, since interaction rhythm can change.

For discoverability, consider a one-time hint such as “Double tap to zoom.” Hidden gestures reduce usability when not obvious.

Testing Strategy

Automated UI tests for tap timing can be fragile if assertions depend on animation timing. Keep tests robust by validating state changes instead of animation frame moments.

swift
1// Pseudocode style expectation
2// 1. Send one tap and assert selection state changed.
3// 2. Send double tap and assert zoom state changed.
4// 3. Assert single tap action did not run during double tap.

Manual testing checklist:

  • Fast double tap.
  • Slow double tap.
  • Single tap after double tap.
  • Interaction inside scrollable container.

This catches most coordination regressions.

Common Pitfalls

A common pitfall is adding both recognizers without setting failure dependency, which causes duplicate or incorrect actions. Another issue is handling business logic directly in gesture callbacks, leading to frame drops. Teams also forget to enable user interaction on image views, so recognizers never fire. Gesture conflicts with scroll views are another frequent source of inconsistent behavior. Finally, accessibility is often treated late, resulting in gesture-only controls that some users cannot reliably trigger.

Summary

  • Use separate recognizers for single and double tap on the same view.
  • Make single tap wait for double tap failure with require(toFail:).
  • Keep handlers fast and move heavy work out of UI callbacks.
  • Define gesture conflict policy explicitly when scroll and zoom gestures exist.
  • Provide accessible alternatives for critical actions not everyone can perform via double tap.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.