Bird
Raised Fist0
iOS Swiftmobile~7 mins

Gesture recognition (drag, magnify, rotate) in iOS Swift

Choose your learning style10 modes available
Introduction

Gesture recognition lets users interact with your app by touching the screen in natural ways like dragging, pinching, or rotating. It makes apps feel alive and easy to use.

You want users to move an object on the screen by dragging it with their finger.
You want users to zoom in or out on a picture by pinching with two fingers.
You want users to rotate an image or shape by twisting two fingers.
You want to add fun and intuitive controls to a drawing or photo app.
You want to respond to common touch gestures to improve app usability.
Syntax
iOS Swift
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
view.addGestureRecognizer(panGesture)

let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch))
view.addGestureRecognizer(pinchGesture)

let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(handleRotation))
view.addGestureRecognizer(rotationGesture)

@objc func handlePan(_ gesture: UIPanGestureRecognizer) {
  // code to move view
}

@objc func handlePinch(_ gesture: UIPinchGestureRecognizer) {
  // code to zoom view
}

@objc func handleRotation(_ gesture: UIRotationGestureRecognizer) {
  // code to rotate view
}
You add gesture recognizers to a view to detect user touches.
Each gesture recognizer calls a method when the gesture happens.
Examples
This adds a drag (pan) gesture to a view. When the user drags, handlePan runs.
iOS Swift
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
view.addGestureRecognizer(panGesture)
This adds a pinch gesture to zoom in or out. The handlePinch method will be called.
iOS Swift
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch))
view.addGestureRecognizer(pinchGesture)
This adds a rotation gesture to rotate the view. The handleRotation method will handle it.
iOS Swift
let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(handleRotation))
view.addGestureRecognizer(rotationGesture)
Sample App

This app shows a blue square you can drag, pinch to zoom, and rotate with your fingers. The gestures update the square's position, size, and angle smoothly.

iOS Swift
import UIKit

class ViewController: UIViewController {
  let square = UIView()
  var currentRotation: CGFloat = 0
  var currentScale: CGFloat = 1
  var currentTranslation = CGPoint.zero

  override func viewDidLoad() {
    super.viewDidLoad()
    square.frame = CGRect(x: 100, y: 100, width: 150, height: 150)
    square.backgroundColor = .systemBlue
    view.addSubview(square)

    let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
    square.addGestureRecognizer(panGesture)

    let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch))
    square.addGestureRecognizer(pinchGesture)

    let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(handleRotation))
    square.addGestureRecognizer(rotationGesture)

    square.isUserInteractionEnabled = true
  }

  @objc func handlePan(_ gesture: UIPanGestureRecognizer) {
    let translation = gesture.translation(in: view)
    if gesture.state == .changed || gesture.state == .ended {
      let newX = currentTranslation.x + translation.x
      let newY = currentTranslation.y + translation.y
      square.transform = CGAffineTransform.identity
        .translatedBy(x: newX, y: newY)
        .scaledBy(x: currentScale, y: currentScale)
        .rotated(by: currentRotation)
    }
    if gesture.state == .ended {
      currentTranslation.x += translation.x
      currentTranslation.y += translation.y
    }
  }

  @objc func handlePinch(_ gesture: UIPinchGestureRecognizer) {
    if gesture.state == .changed || gesture.state == .ended {
      let scale = currentScale * gesture.scale
      square.transform = CGAffineTransform.identity
        .translatedBy(x: currentTranslation.x, y: currentTranslation.y)
        .scaledBy(x: scale, y: scale)
        .rotated(by: currentRotation)
    }
    if gesture.state == .ended {
      currentScale *= gesture.scale
      gesture.scale = 1
    }
  }

  @objc func handleRotation(_ gesture: UIRotationGestureRecognizer) {
    if gesture.state == .changed || gesture.state == .ended {
      let rotation = currentRotation + gesture.rotation
      square.transform = CGAffineTransform.identity
        .translatedBy(x: currentTranslation.x, y: currentTranslation.y)
        .scaledBy(x: currentScale, y: currentScale)
        .rotated(by: rotation)
    }
    if gesture.state == .ended {
      currentRotation += gesture.rotation
      gesture.rotation = 0
    }
  }
}
OutputSuccess
Important Notes

Remember to enable user interaction on views you want to gesture on by setting isUserInteractionEnabled = true.

Gesture recognizers can work together, but sometimes you need to manage conflicts.

Use the gesture's state to update your view only when the gesture changes or ends.

Summary

Gesture recognizers detect user touches like drag, pinch, and rotate.

Add gesture recognizers to views and handle their actions to update UI.

Combine translation, scale, and rotation transforms to move and change views smoothly.

Practice

(1/5)
1. Which gesture recognizer in SwiftUI detects a dragging motion on a view?
easy
A. MagnificationGesture
B. RotationGesture
C. DragGesture
D. TapGesture

Solution

  1. Step 1: Understand gesture types

    DragGesture detects dragging motions, MagnificationGesture detects pinch zoom, RotationGesture detects rotation, and TapGesture detects taps.
  2. Step 2: Match gesture to dragging

    Since dragging means moving finger across the screen, DragGesture is the correct recognizer.
  3. Final Answer:

    DragGesture -> Option C
  4. Quick Check:

    DragGesture = dragging motion [OK]
Hint: DragGesture is for dragging, Magnification for pinch zoom [OK]
Common Mistakes:
  • Confusing MagnificationGesture with dragging
  • Choosing TapGesture for drag
  • Mixing RotationGesture with drag
2. Which of the following is the correct syntax to add a rotation gesture recognizer to a SwiftUI view?
easy
A. .gesture(RotationGesture().onChanged { angle in /* code */ })
B. .onTapGesture { /* code */ }
C. .gesture(DragGesture().onEnded { _ in /* code */ })
D. .gesture(MagnificationGesture().onChanged { scale in /* code */ })

Solution

  1. Step 1: Identify rotation gesture syntax

    RotationGesture() is the correct gesture for rotation, and .gesture() modifier adds it to a view.
  2. Step 2: Confirm onChanged closure usage

    onChanged receives the rotation angle, so the syntax .gesture(RotationGesture().onChanged { angle in ... }) is correct.
  3. Final Answer:

    .gesture(RotationGesture().onChanged { angle in /* code */ }) -> Option A
  4. Quick Check:

    RotationGesture syntax = .gesture(RotationGesture().onChanged { angle in /* code */ }) [OK]
Hint: Use .gesture(RotationGesture().onChanged) for rotation [OK]
Common Mistakes:
  • Using DragGesture instead of RotationGesture
  • Using .onTapGesture for rotation
  • Confusing MagnificationGesture with rotation
3. What will be the effect of this SwiftUI code snippet on a view?
Image("photo")
  .scaleEffect(scale)
  .rotationEffect(angle)
  .offset(dragAmount)
  .gesture(
    DragGesture()
      .onChanged { dragAmount = $0.translation }
      .onEnded { _ in dragAmount = .zero }
  )
  .gesture(
    MagnificationGesture()
      .onChanged { scale = $0 }
  )
  .gesture(
    RotationGesture()
      .onChanged { angle = $0 }
  )
medium
A. Only dragging works; zoom and rotation gestures are ignored.
B. The image can be dragged, zoomed, and rotated by user gestures.
C. Only zooming works; drag and rotation gestures are ignored.
D. The image is static and does not respond to gestures.

Solution

  1. Step 1: Analyze gesture modifiers

    The code adds three gestures: DragGesture updates dragAmount offset, MagnificationGesture updates scale, RotationGesture updates angle.
  2. Step 2: Understand combined effects

    The view applies scaleEffect, rotationEffect, and offset using these state variables, so all gestures affect the image interactively.
  3. Final Answer:

    The image can be dragged, zoomed, and rotated by user gestures. -> Option B
  4. Quick Check:

    All gestures update view transforms = The image can be dragged, zoomed, and rotated by user gestures. [OK]
Hint: Multiple gestures update scale, rotation, and offset simultaneously [OK]
Common Mistakes:
  • Assuming only one gesture works at a time
  • Ignoring that gestures update state variables
  • Thinking gestures override each other
4. Identify the error in this SwiftUI gesture code snippet:
Circle()
  .gesture(DragGesture().onChanged { value in
    dragAmount = value.translation
  })
  .gesture(MagnificationGesture().onChanged { scale = $0 })
medium
A. Only the MagnificationGesture will work; DragGesture is ignored.
B. Both gestures work correctly without conflict.
C. The code will cause a compile-time error due to multiple gestures.
D. DragGesture will override MagnificationGesture, so only drag works.

Solution

  1. Step 1: Understand gesture modifiers stacking

    Applying multiple .gesture modifiers separately causes only the last one to be active.
  2. Step 2: Identify which gesture is active

    Since MagnificationGesture is added last, it overrides DragGesture, so only magnification works.
  3. Final Answer:

    Only the MagnificationGesture will work; DragGesture is ignored. -> Option A
  4. Quick Check:

    Last .gesture overrides previous = Only the MagnificationGesture will work; DragGesture is ignored. [OK]
Hint: Multiple .gesture modifiers override; combine gestures with simultaneousGesture [OK]
Common Mistakes:
  • Assuming both gestures work independently
  • Expecting compile error for multiple gestures
  • Thinking first gesture always wins
5. You want to allow a user to drag, zoom, and rotate a photo simultaneously in SwiftUI. Which approach correctly combines these gestures so all work together smoothly?
hard
A. Use only one gesture recognizer that detects drag, zoom, and rotate at once.
B. Add three separate .gesture modifiers for each gesture on the view.
C. Use .gesture for DragGesture and ignore zoom and rotate gestures.
D. Use .simultaneousGesture to combine DragGesture, MagnificationGesture, and RotationGesture on the view.

Solution

  1. Step 1: Understand gesture combination in SwiftUI

    Multiple .gesture modifiers override each other, so to combine gestures, use .simultaneousGesture.
  2. Step 2: Apply simultaneousGesture for all three

    By nesting .simultaneousGesture for DragGesture, MagnificationGesture, and RotationGesture, all gestures work together smoothly.
  3. Final Answer:

    Use .simultaneousGesture to combine DragGesture, MagnificationGesture, and RotationGesture on the view. -> Option D
  4. Quick Check:

    Combine gestures with simultaneousGesture = Use .simultaneousGesture to combine DragGesture, MagnificationGesture, and RotationGesture on the view. [OK]
Hint: Combine gestures with .simultaneousGesture for multi-touch support [OK]
Common Mistakes:
  • Adding multiple .gesture modifiers separately
  • Expecting one gesture to handle all types
  • Ignoring zoom and rotate gestures
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard