iOS
UIView
Touch Events
Controller
Swift

UIView touch event in controller

Interview Questions practice on Codemia

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

Browse interview questions

Introduction

Touch handling in iOS can happen in a view subclass, in a view controller, or through a gesture recognizer. The right choice depends on what you are trying to detect. If you just need tap-like interaction in a controller, a gesture recognizer is usually cleaner than overriding raw touch methods.

Raw touchesBegan, touchesMoved, and related methods still matter when you need fine-grained touch tracking. The important detail is understanding where those events actually arrive in the responder chain.

Where Touch Events Should Live

UIView inherits from UIResponder, so a view can receive low-level touch callbacks directly. A UIViewController also participates in the responder system, but the controller is not usually the first place touch events land. The touched view receives them first.

That means:

  • use a custom UIView subclass when the view itself owns the interaction,
  • use a gesture recognizer when the controller only needs high-level gestures,
  • override controller touch methods only when you specifically want controller-level raw touch handling.

For most apps, gesture recognizers are the best default.

Preferred Approach: Gesture Recognizer in the Controller

If your controller wants to react when the user taps a view, add a UITapGestureRecognizer:

swift
1import UIKit
2
3final class DemoViewController: UIViewController {
4    private let boxView: UIView = {
5        let view = UIView()
6        view.translatesAutoresizingMaskIntoConstraints = false
7        view.backgroundColor = .systemBlue
8        return view
9    }()
10
11    override func viewDidLoad() {
12        super.viewDidLoad()
13        view.backgroundColor = .white
14        view.addSubview(boxView)
15
16        NSLayoutConstraint.activate([
17            boxView.widthAnchor.constraint(equalToConstant: 160),
18            boxView.heightAnchor.constraint(equalToConstant: 160),
19            boxView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
20            boxView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
21        ])
22
23        let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
24        boxView.addGestureRecognizer(tap)
25    }
26
27    @objc private func handleTap() {
28        print("Box tapped")
29    }
30}

This keeps the touch interpretation in UIKit's gesture system instead of forcing you to manually inspect UITouch objects.

When a Custom View Is Better

If the interaction belongs to the view itself, such as drawing, dragging, or custom hit-testing, override touch methods in a UIView subclass:

swift
1import UIKit
2
3final class DrawingView: UIView {
4    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
5        guard let touch = touches.first else { return }
6        print("Touch began at", touch.location(in: self))
7    }
8
9    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
10        guard let touch = touches.first else { return }
11        print("Touch moved to", touch.location(in: self))
12    }
13
14    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
15        print("Touch ended")
16    }
17}

This is the right place for raw touch state because the view is the thing being interacted with.

Controller-Level Raw Touches

You can override touch methods in a UIViewController, but it is usually a specialized choice:

swift
1override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
2    super.touchesBegan(touches, with: event)
3    print("Controller noticed a touch")
4}

This works only when the responder chain reaches the controller. If a child view handles the touch or a gesture recognizer consumes it, the controller may not see what you expect. That is why controller-level raw touch handling is often surprising.

Common Pitfalls

  • Overriding raw touch methods in the controller when a gesture recognizer would be simpler and more reliable.
  • Expecting the controller to receive every touch before the view does. The touched view usually gets first chance.
  • Forgetting isUserInteractionEnabled on custom views that should respond to gestures.
  • Putting heavy work inside touch callbacks, which can make scrolling and animations feel laggy.
  • Handling only touchesBegan and ignoring moved, ended, or cancelled states when the interaction needs full tracking.

Summary

  • Gesture recognizers are usually the cleanest way to handle taps and common gestures in a controller.
  • Custom UIView subclasses are the right place for raw touch tracking owned by the view itself.
  • Controller-level touch overrides are possible, but they are not the best default.
  • The responder chain determines where touch events actually arrive.
  • Choose the highest-level API that matches the interaction you need.

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.