Detecting gestures used to be tricky in the early days, but that changed with the introduction of the UIGestureRecognizer
class in iOS 3.2. In this post, I show you how to use a tap gesture recognizer in Swift using the UITapGestureRecognizer
class. We create a simple application and add a tap gesture recognizer to detect single and double taps.
Setting Up the Project in Xcode
Fire up Xcode and create a blank project by choosing the App template from the iOS > Application section.
Name the project Taps, set Interface to Storyboard, and Language to Swift.
Open ViewController.swift and declare an outlet with name tappableView
of type UIView!
. We use a didSet
property observer to set the background color of the view to a bright red color. Using didSet
property observers to configure outlets is a pattern I use a lot.
import UIKit
class ViewController: UIViewController {
// MARK: - Properties
@IBOutlet private var tappableView: UIView! {
didSet {
tappableView.backgroundColor = .red
}
}
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
}
}
Open Main.storyboard, add a view to the view controller scene, and add constraints to center the view in the view controller's view. With the view selected, open the Connections Inspector on the right and connect the view to the outlet we defined in the ViewController
class.
Build and run the application in a simulator. You should see a white view with a red view at its center.
Adding a Tap Gesture Recognizer to a View
We have two options to add a tap gesture recognizer to a view, in code or in Interface Builder. The result is identical, but the execution is different.
Adding a Tap Gesture Recognizer in Interface Builder
I never add gesture recognizers in Interface Builder, but that is a personal choice. By adding gesture recognizers in code, it is easier to understand how the view controller behaves by browsing its implementation. You don't need to switch between the code editor and Interface Builder.
Open Main.storyboard and drag a tap gesture recognizer from the Object Library and drop it onto the view we added earlier. The tap gesture recognizer appears in the Document Outline on the left.
We have added a tap gesture recognizer to the view, but we haven't attached an action to it. Open ViewController.swift and define an action. An action is another name for a method that is exposed to Interface Builder. The action accepts a single argument, the tap gesture recognizer.
// MARK: - Actions
@IBAction func didTapView(_ sender: UITapGestureRecognizer) {
print("did tap view", sender)
}
Revisit Main.storyboard and select the tap gesture recognizer in the Document Outline. Open the Connections Inspector on the right and drag from selector in the Sent Actions section to the view controller in the Document Outline. A menu pops up that displays the didTapView(_:)
action.
Build and run the application, tap the red view, and inspect the output in the console. The output confirms that we successfully added a tap gesture recognizer to the view.
didTapView(_:), 29, /Users/Bart/Desktop/Taps/Taps/ViewController.swift <UITapGestureRecognizer: 0x7ffc83508600; state = Ended; view = <UIView 0x7ffc74e0ab40>; target= <(action=didTapView:, target=<Taps.ViewController 0x7ffc835082a0>)>>
Adding a Tap Gesture Recognizer in Code
Remove the tap gesture recognizer in Interface Builder, revisit ViewController.swift, and navigate to the viewDidLoad()
method. We initialize a UITapGestureRecognizer
instance by invoking the init(target:action:)
initializer. The target is the view controller and the action is the didTapView(_:)
method we defined earlier.
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
// Initialize Tap Gesture Recognizer
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapView(_:)))
}
// MARK: - Actions
@IBAction func didTapView(_ sender: UITapGestureRecognizer) {
print("did tap view", sender)
}
We don't need to prefix the didTapView(_:)
method with the IBAction
attribute because we don't use Interface Builder to configure the tap gesture recognizer. If we remove the IBAction
attribute, we need to prefix the didTapView(_:)
method with the objc
attribute instead. The objc
attribute exposes the method to the Objective-C runtime. This is a more advanced topic that I won't cover in this post.
// MARK: - Actions
@objc func didTapView(_ sender: UITapGestureRecognizer) {
print("did tap view", sender)
}
If we omit the objc
attribute, the compiler throws an error.
Before we can build and run the application, we need to add the tap gesture recognizer to the view. We invoke the addGestureRecognizer(_:)
method on tappableView
, passing in the tap gesture recognizer.
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
// Initialize Tap Gesture Recognizer
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapView(_:)))
// Add Tap Gesture Recognizer
tappableView.addGestureRecognizer(tapGestureRecognizer)
}
Build and run the application one more time to make sure we didn't break anything. Tap the view and inspect the output in the console.
Detecting Double Taps With a Tap Gesture Recognizer In Swift
A tap gesture recognizer can detect single taps and double taps. Let's configure the tap gesture recognizer to detect double taps instead of single taps. In viewDidLoad()
, we set the numberOfTapsRequired
property of the tap gesture recognizer to 2
. It defaults to 1
.
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
// Initialize Tap Gesture Recognizer
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapView(_:)))
// Configure Tap Gesture Recognizer
tapGestureRecognizer.numberOfTapsRequired = 2
// Add Tap Gesture Recognizer
tappableView.addGestureRecognizer(tapGestureRecognizer)
}
Build and run the application to test the change. Nothing is printed to the console if you tap the view once. The didTapView(_:)
method is called if you tap the view twice. The output in the console confirms this. The UITapGestureRecognizer
class encapsulates the logic for detecting single, double, and triple taps. Your task is limited to configuring the tap gesture recognizer.