UIGestureRecognizer
UIImageView
iOS Development
Swift Programming
Mobile App Development

UIGestureRecognizer on UIImageView

Interview Questions practice on Codemia

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

Browse interview questions

Introduction

Using UIGestureRecognizer with a UIImageView is the standard way to make an image tappable, draggable, or zoomable in iOS. The main detail people miss is that UIImageView has isUserInteractionEnabled set to false by default, so gestures will not fire until you turn interaction on.

Start with a Tap Gesture

The simplest interactive image is a tap target. After enabling interaction, add a recognizer and implement the handler.

swift
1import UIKit
2
3final class PhotoViewController: UIViewController {
4    private let imageView = UIImageView(image: UIImage(named: "sample"))
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8
9        imageView.frame = view.bounds
10        imageView.contentMode = .scaleAspectFit
11        imageView.isUserInteractionEnabled = true
12        view.addSubview(imageView)
13
14        let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
15        imageView.addGestureRecognizer(tap)
16    }
17
18    @objc private func handleTap(_ recognizer: UITapGestureRecognizer) {
19        let point = recognizer.location(in: imageView)
20        print("Tapped at \(point)")
21    }
22}

Without isUserInteractionEnabled = true, the recognizer will never receive touches, even if everything else is wired correctly.

Add Pinch and Pan for Image Exploration

If the image needs zoom and drag behavior, add pinch and pan recognizers. Use incremental transforms so movement feels smooth.

swift
1import UIKit
2
3extension PhotoViewController: UIGestureRecognizerDelegate {
4    func configureZoomAndPan() {
5        let pinch = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(_:)))
6        let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
7
8        pinch.delegate = self
9        pan.delegate = self
10
11        imageView.addGestureRecognizer(pinch)
12        imageView.addGestureRecognizer(pan)
13    }
14
15    @objc private func handlePinch(_ recognizer: UIPinchGestureRecognizer) {
16        guard recognizer.state == .began || recognizer.state == .changed else { return }
17
18        imageView.transform = imageView.transform.scaledBy(x: recognizer.scale, y: recognizer.scale)
19        recognizer.scale = 1.0
20    }
21
22    @objc private func handlePan(_ recognizer: UIPanGestureRecognizer) {
23        let translation = recognizer.translation(in: view)
24        guard recognizer.state == .began || recognizer.state == .changed else { return }
25
26        imageView.center = CGPoint(
27            x: imageView.center.x + translation.x,
28            y: imageView.center.y + translation.y
29        )
30
31        recognizer.setTranslation(.zero, in: view)
32    }
33}

Resetting the recognizer's scale and translation each step avoids compounding the full gesture delta over and over.

Allow Simultaneous Gesture Recognition When Needed

Pinch and pan often need to work together. Implement the gesture recognizer delegate when simultaneous recognition makes sense.

swift
1func gestureRecognizer(
2    _ gestureRecognizer: UIGestureRecognizer,
3    shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer
4) -> Bool {
5    return true
6}

Do not return true blindly for every app. If the image view sits inside a scroll view or another interactive parent, you may need more selective logic so gestures do not fight each other.

Common Pitfalls

The biggest mistake is forgetting that UIImageView does not accept user interaction by default. That one property explains a large share of "gesture recognizer not working" bugs.

Another common issue is adding recognizers repeatedly in reusable views or cell configuration methods. That can lead to duplicate callbacks firing for one gesture. Configure recognizers once, or remove old ones before reattaching them.

People also leave zoom and pan unbounded. Without min and max scale or recentering logic, the image can drift or grow until the interaction feels broken.

Finally, if the image view lives inside a table view, collection view, or scroll view, test gesture conflicts on a real device. The recognizer wiring may be correct, but the interaction still needs to feel intentional.

Accessibility matters too. If tapping the image performs an action, consider adding an accessibility label or alternate control so the interaction is still discoverable for assistive technologies consistently everywhere.

Summary

  • Enable isUserInteractionEnabled on the UIImageView before adding recognizers.
  • Use UITapGestureRecognizer for simple tap interactions.
  • Add pinch and pan recognizers for zoomable or draggable images.
  • Allow simultaneous recognition only when the gesture combination really makes sense.
  • Watch for duplicate recognizers, gesture conflicts, and unbounded transforms.

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.