iOS
Pan Gesture
Swipe Gesture
User Interface
Gesture Recognition

What is the difference between Pan and Swipe in iOS?

Interview Questions practice on Codemia

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

Browse interview questions

Introduction

UIPanGestureRecognizer and UISwipeGestureRecognizer both react to finger movement, but they model very different user intent. Pan is continuous and tracks movement frame by frame. Swipe is discrete and signals that a directional action happened once.

Gesture Semantics and Event Model

The most important difference is event frequency.

  • Pan emits updates across .began, .changed, and .ended states.
  • Swipe fires a single recognition callback after movement crosses direction and velocity thresholds.

If your interface needs to follow the finger in real time, use pan. If your interface needs a command like next page or delete item, use swipe.

This decision affects interaction quality more than most animation tuning.

Implementing a Pan Interaction

Pan works well for cards, maps, custom sliders, and canvas tools because translation and velocity are available during motion.

swift
1import UIKit
2
3final class PanCardViewController: UIViewController {
4    private let card = UIView()
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8        view.backgroundColor = .systemBackground
9
10        card.frame = CGRect(x: 60, y: 180, width: 220, height: 140)
11        card.backgroundColor = .systemBlue
12        card.layer.cornerRadius = 16
13        view.addSubview(card)
14
15        let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
16        card.addGestureRecognizer(pan)
17    }
18
19    @objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
20        let delta = gesture.translation(in: view)
21
22        if gesture.state == .began || gesture.state == .changed {
23            card.center = CGPoint(x: card.center.x + delta.x, y: card.center.y + delta.y)
24            gesture.setTranslation(.zero, in: view)
25        }
26
27        if gesture.state == .ended {
28            let velocity = gesture.velocity(in: view)
29            if abs(velocity.x) > 900 {
30                UIView.animate(withDuration: 0.25) {
31                    self.card.center.x += velocity.x > 0 ? 120 : -120
32                }
33            }
34        }
35    }
36}

Using incremental translation with setTranslation(.zero, in:) prevents double counting and keeps motion stable.

Implementing a Swipe Command

Swipe is ideal for simple directional commands. It is not intended for object dragging.

swift
1import UIKit
2
3final class SwipeActionsViewController: UIViewController {
4    override func viewDidLoad() {
5        super.viewDidLoad()
6        view.backgroundColor = .secondarySystemBackground
7
8        let left = UISwipeGestureRecognizer(target: self, action: #selector(onSwipe(_:)))
9        left.direction = .left
10
11        let right = UISwipeGestureRecognizer(target: self, action: #selector(onSwipe(_:)))
12        right.direction = .right
13
14        view.addGestureRecognizer(left)
15        view.addGestureRecognizer(right)
16    }
17
18    @objc private func onSwipe(_ gesture: UISwipeGestureRecognizer) {
19        switch gesture.direction {
20        case .left:
21            print("Navigate forward")
22        case .right:
23            print("Navigate back")
24        default:
25            break
26        }
27    }
28}

Because swipe is discrete, callback logic stays simple and deterministic.

Gesture Coordination With Scroll Views

Real screens often combine scroll views, edge gestures, and custom recognizers. Without explicit coordination, recognizers can conflict.

Typical options:

  • Use require(toFail:) when one gesture should dominate.
  • Implement delegate rules for simultaneous recognition only when truly needed.
  • Scope recognizers to smaller subviews instead of entire screens.
swift
1final class Coordinator: NSObject, UIGestureRecognizerDelegate {
2    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
3                           shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
4        return false
5    }
6}

Testing on device is essential because simulator trackpad input does not fully match touch behavior.

Practical Selection Guide

Use pan when:

  • UI elements need continuous dragging.
  • Velocity should influence ending animation.
  • The user must control position directly.

Use swipe when:

  • One directional action is enough.
  • UI should not move continuously under finger.
  • You need a command gesture with minimal state handling.

When both are needed, define priority explicitly and document it so future changes do not break interaction intent.

Common Pitfalls

  • Using swipe for drag behavior and getting jumpy motion.
  • Applying absolute translation repeatedly in pan handlers without resetting.
  • Ignoring recognizer conflicts with table views or collection views.
  • Only reacting on .ended for pan and making interaction feel laggy.
  • Forgetting device testing for edge cases such as one handed thumb gestures.

Summary

  • Pan is continuous and reports translation plus velocity over time.
  • Swipe is discrete and signals one directional command.
  • Pan is best for manipulation, swipe is best for navigation style actions.
  • Recognizer priority and conflict rules are critical on complex screens.
  • Match gesture type to user intent before polishing animations.

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.