Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 56

Haptic Feedback for User Interactions

Recommended resources

Hello! Welcome to the final lesson in our module on "Interactive Animations and Transitions."

In our previous lesson, you mastered the implementation of custom view controller transitions with UIViewControllerAnimatedTransitioning. This was a significant step in learning how to create a unique and polished user experience, moving beyond standard system navigation.

Today, we'll add another layer of polish by exploring a different sensory dimension: touch. The goal of this lesson is to integrate haptic feedback (UIImpactFeedbackGenerator) to complement key user interactions. Haptics provide subtle physical feedback that can make an app feel more responsive, confirm actions, and create a higher-quality user experience.

1. The "Why" and "What" of Haptic Feedback

Haptic feedback is the use of touch sensations, like vibrations, to communicate with the user. In iOS, this is powered by the Taptic Engine. When used thoughtfully, haptics can provide confirmation for an action (like a successful save), enhance the feeling of a physical interaction (like a switch toggling), or alert the user to an important event.

Apple provides three main classes, all subclasses of UIFeedbackGenerator, to produce standard haptic patterns. This saves you from having to design them yourself and ensures a consistent feel across the OS.

To get a quick overview of these three types, please watch the beginning of the following video.

Swift Tutorial - Haptic Feedback - Taptic Engine

This video from Sean Allen's channel provides a concise introduction to the three main feedback generators and their common use cases.

Watch from the beginning to 01:33. Focus on understanding the distinct purpose of UIImpactFeedbackGenerator, UINotificationFeedbackGenerator, and UISelectionFeedbackGenerator.

As a quick summary, the three main generators are:

  • UIImpactFeedbackGenerator: Used to indicate a physical impact, like a view "snapping" into place or two UI elements colliding.
  • UINotificationFeedbackGenerator: Used to communicate the outcome of an action: success, failure, or a warning.
  • UISelectionFeedbackGenerator: Used to indicate a change in selection, like scrolling through a picker wheel.

2. Implementing the Feedback Generators

Now, let's look at the code required to trigger these different haptic patterns. The process is straightforward for all three types: you create an instance of the appropriate generator and then call a method to trigger the feedback.

This screenshot shows a simple UI for testing the various feedback types we'll be discussing.

Haptic Feedback Demonstration UI
A simple app UI with buttons to trigger different haptic feedback styles, such as notification success/error/warning, impact heavy/medium/light, and selection.

UIImpactFeedbackGenerator

This is the most versatile generator and the main focus of our lesson. It's perfect for adding feedback to button taps, drag-and-drop actions, or completing a gesture. It comes with several built-in styles.

How to Play Haptic Feedback - using UIFeedbackGenerator

The article "How to Play Haptic Feedback" by Sarunw provides a clear, text-based summary of the different impact styles and how to implement them.

Read the section titled "UIImpactFeedbackGenerator". Note the five presets listed (light, medium, heavy, soft, rigid) and the basic code example for generating a soft impact.

The basic implementation looks like this:

// 1. Create a generator with a specific style
let generator = UIImpactFeedbackGenerator(style: .heavy)

// 2. Trigger the feedback
generator.impactOccurred()

You can even provide a custom intensity:

// Intensity must be a CGFloat between 0.0 and 1.0
generator.impactOccurred(intensity: 0.75)

UINotificationFeedbackGenerator and UISelectionFeedbackGenerator

The implementation for the other two generators is just as simple. The key is choosing the right one for the job.

  • For notifications, you call notificationOccurred() with the appropriate type: .success, .error, or .warning.
  • For selection changes, you call selectionChanged().

The following video segments provide a practical coding demonstration for all three generator types.

Swift Tutorial - Haptic Feedback - Taptic Engine

Let's return to Sean Allen's video to see how each of these generators is implemented in code.

Please watch the following segments: Notification Feedback (02:52 - 04:18): See how to trigger .error, .success, and .warning notifications. Impact Feedback (04:18 - 05:22): Watch the implementation of .light, .medium, and .heavy impact feedback. We will cover the prepare() method next. Selection Feedback (06:44 - 07:19): See the simple implementation for selection changes.


3. Professional Practice: Latency and Management

While the basic implementation is easy, there are two key practices that distinguish professional, high-quality haptic integration from a basic one.

Reducing Latency with prepare()

The Taptic Engine can have a small amount of latency—a slight delay between when you request feedback and when it actually occurs. For many interactions, this is unnoticeable. However, when you need to precisely sync a haptic with a visual or audio cue (like a sound effect), this latency matters.

To solve this, UIFeedbackGenerator provides a prepare() method. Calling this method "warms up" the Taptic Engine, so that when you later trigger the feedback, it plays almost instantaneously.

Swift Tutorial - Haptic Feedback - Taptic Engine

Let's explore the concept of preparing the generator to reduce latency. This is a key detail for professional-grade feedback.

Watch the segment from 04:49 to 06:18. Pay close attention to the explanation of why and when you would use generator.prepare(), such as before starting a network call.

The lifecycle is simple:

  1. Anticipate the feedback: At the start of an operation (e.g., user taps "Save," network request begins), create your generator and call prepare().
  2. Trigger the feedback: When the operation completes (e.g., network request succeeds), call impactOccurred() or notificationOccurred().
  3. Release or re-prepare: The Taptic Engine returns to an idle state after the feedback plays. If you don't need it anymore, you can let the generator be deallocated. If you anticipate another haptic soon, you can call prepare() again.

Centralizing Logic with a HapticsManager

As you start adding haptics throughout your app, you'll find yourself writing the same generator code in many different view controllers. A cleaner, more professional approach is to encapsulate this logic in a dedicated manager class. This follows the principle of Separation of Concerns and makes your code more maintainable.

A common pattern is to create a singleton HapticsManager.

Building Spotify App in Swift 5 & UIKit - Part 26 - Haptics (Xcode 12, 2021, Swift 5) - Build App

The channel iOS Academy has a great video showing how to build a HapticsManager singleton and integrate it into a real app.

Watch these segments to see the full pattern: Creating the Singleton (01:20 - 01:44): See how a final class with a shared static property and a private initializer is created. Adding Functions (01:44 - 03:22): Observe the creation of vibrateForSelection() and vibrate(for:) methods that encapsulate the generator logic. Thread Safety (03:22 - 03:43): This is a crucial professional tip. Haptic feedback must be triggered on the main thread. Notice how the code is wrapped in a DispatchQueue.main.async block. Integration Examples (03:43 - 06:11): See how cleanly the manager is called from different parts of the app, such as a table view's didSelectItemAt method and the completion block of a save operation.

Using a manager simplifies callsites dramatically. Instead of several lines of boilerplate, you have a single, expressive line of code:

HapticsManager.shared.vibrate(for: .success)


Conclusion

You now have the tools to add a subtle but powerful layer of polish to your applications. Haptic feedback, when used appropriately, bridges the gap between the digital and physical worlds, making your app feel more intuitive and responsive.

Key Takeaways:

  • There are three main feedback generators: UIImpactFeedbackGenerator (for impacts), UINotificationFeedbackGenerator (for success/warning/error), and UISelectionFeedbackGenerator (for selection changes).
  • UIImpactFeedbackGenerator is highly versatile, offering styles like .light, .medium, and .heavy to match different interaction weights.
  • To minimize latency and sync haptics with visual events, call the generator's prepare() method ahead of time.
  • For clean and reusable code, encapsulate haptic logic in a centralized HapticsManager, ensuring all feedback is triggered on the main thread.
  • Use haptics mindfully. They should complement an action and provide meaningful feedback, not distract or annoy the user.

Preview of the Next Module:

This lesson concludes our module on "Interactive Animations and Transitions." You've learned to build beautiful, dynamic, and interactive user interfaces. However, complex animations and view hierarchies can sometimes come at a cost: performance.

In our next module, "UI & Rendering Performance Optimization," we will tackle this head-on. The first lesson will teach you how to profile rendering performance and identify dropped frames using the Core Animation instrument. This is an essential skill for ensuring that the sophisticated animations you now know how to build are not just beautiful, but also buttery smooth.