Haptic Feedbackを実装する

Haptic Feedbackとは

ユーザーの何かしらのアクションに対して「ドゥッ」とiPhoneをバイブさせるアレ。
スタートトゥデイさんの記事の説明を拝借すると、

iPhone 6s 以降に搭載された Taptic Engineというハードウェアによる振動で、ユーザーのアクションに対するフィードバックを表現します。

だそうです。

UIScrollViewのrefreshControlプロパティによるpull to refreshをした際にもこれが使われている。
Facebookやinstagramの動画リスト面で動画を切り替える時にも使われている。
(ちなみにpull to refreshの実装方法は以下)

kitoko552.hatenablog.com

実装方法

UIFeedbackGeneratorを使う。
UIFeedbackGenerator自体はabstract classで、実際に使うのはサブクラスのUIImpactFeedbackGenerator/UISelectionFeedbackGenerator/UINotificationFeedbackGeneratorの3つ。

UIImpactFeedbackGenerator

公式リファレンスより、

A concrete UIFeedbackGenerator subclass that creates haptics to simulate physical impacts.

と書かれていることから、実際の衝突を表現したい時に使うと良さそう。pull to refreshはこれかなと。
UIImpactFeedbackStyleでlight/medium/heavyいずれかのスタイル(強さ)を指定できる。

final class ViewController: UIViewController {
    private let feedbackGenerator: UIImpactFeedbackGenerator = {
        let generator = UIImpactFeedbackGenerator(style: .light)
        generator.prepare()
        return generator
    }()

    // feedbackGenerator.impactOccurred()で発火
}

UISelectionFeedbackGenerator

公式リファレンスより、

A concrete UIFeedbackGenerator subclass that creates haptics to indicate a change in selection.

と書かれていることから、何かを選択したりする時に使うと良さそう。上に書いた「Facebookやinstagramの動画リスト面で動画を切り替える時」はこれっぽい。
こちらはスタイルはなく、1種類のみとなる。

final class ViewController: UIViewController {
    private let feedbackGenerator: UISelectionFeedbackGenerator = {
        let generator = UISelectionFeedbackGenerator()
        generator.prepare()
        return generator
    }()

    // feedbackGenerator.selectionChanged()で発火
}

UINotificationFeedbackGenerator

公式リファレンスより、

A concrete UIFeedbackGenerator subclass that creates haptics to communicate successes, failures, and warnings.

と書かれていることから、何かしらのアクションが成功・失敗した時に使うと良さそう。Face ID/Touch IDを使う時とか?
UINotificationFeedbackTypeでsuccess/warning/errorのいずれかを指定できる。こちらはUIImpactFeedbackGeneratorと違って発火時に指定する。

final class ViewController: UIViewController {
    private let feedbackGenerator: UINotificationFeedbackGenerator = {
        let generator = UINotificationFeedbackGenerator()
        generator.prepare()
        return generator
    }()

    // feedbackGenerator.notificationOccured(_ notificationType: UINotificationFeedbackType)で発火
}

prepare()は何者?

上記3種類の全てのfeedbackGeneratorの実装例でprepare()を呼んでいますが、これはUIFeedbackGeneratorに実装されていて、公式リファレンスのDiscussionを読むと、「prepare()を呼んでおくと低レイテンシでfeedbackをトリガーできるよ」と書いてあるので特に事情がない限りは呼んでおいた方が良さそう。

When you call this method, the generator is placed into a prepared state for a short period of time. While the generator is prepared, you can trigger feedback with lower latency.

参考記事

tech.starttoday-tech.com

公式リファレンス

UIImpactFeedbackGenerator - UIKit | Apple Developer Documentation

UISelectionFeedbackGenerator - UIKit | Apple Developer Documentation

UINotificationFeedbackGenerator - UIKit | Apple Developer Documentation

prepare() - UIFeedbackGenerator | Apple Developer Documentation