【コードあり】Swiftで触覚機能を活用してUXを向上させようの巻

## 概要
個人開発アプリで、「地図をロングプレスするとピンを立てることができ、もう1度タップするとピンを削除できる」という挙動を実装しています。その際に、実際にピンが立ったり消えたりしていることは見えますが、あいにくマップはいろんなアイコンが表示されるので、ピンを立てれたかどうかを直感的に把握するのは難しいです。
そこで、「ユーザーに直感的に挙動を伝えることができないか？」と考えたところ、触覚機能を活用する流れになりました。

#### この記事はこんな方におすすめ
- QuickPayやAppStore課金成功時になるあの挙動を再現したい方
- UINotificationFeedbackとUIImpactFeedbackGeneratorについて学びたい方
- iOSアプリでUI/UXを向上させたい方

## UINotificationFeedbackGeneratorについて
UINotificationFeedbackGeneratorは、**「成功・失敗・警告」** の3つのパターンの触覚機能を伝達してくれる機能です。

#### 【UINotificationFeedbackGenerator】コード例

```UINotificationFeedbackGenerator.Swift

    /// ポイント①
    func communicateNotificationtWith(type: UINotificationFeedbackGenerator.FeedbackType) {
        let generator = UINotificationFeedbackGenerator()
        generator.prepare()
        generator.notificationOccurred(type)
    }
 
    /// ポイント②
    @objc private func longPressMapView() {
        communicateNotificationtWith(type: .success)
        //　ピンを立てる処理は割愛
    }

```

##### コード解説
- ポイント①
UINotificationFeedbackGeneratorをインスタンス化して、触覚機能を生成して伝える処理にしています。
ただ、これだけでは触覚機能を使用できないので、ポイント②の実装を加えます。

- ポイント②
今回はマップを長押しした時の挙動で想定していて、ロングプレスされた時に触覚機能をユーザーに伝えています。
この際に、成功することがあらかじめ確定している場合は、引数UINotificationFeedbackGenerator.FeedbackTypeに.successを渡してあげましょう！

※今回は関係ないのでコードは載せませんが、何もせずこのまま実装するとロングプレスが一度で複数回反応してしまうので、対策はしてあげましょう！

### ひとこと
より使いこなせる場面としては、サーバー等のやり取りで成功と失敗の2パターンがある場合、その結果に応じて引数に.errorもしくは、.successを入れてあげればユーザーにとても親切なUXになるような気がします！


## UIImpactFeedbackGenerator 
正直、「UINotificationFeedbackGeneratorとどう違うねん。」とお思いの方、僕も同じ考えです。（笑)
念の為、調べてみました。
クラスの説明では、「物理的なフィードバックをユーザーに伝えるクラス」であるとのことです...。やっぱり一緒やん。

アプリでUIImpactFeedbackGeneratorとUINotificationFeedbackGeneratorを実際に実装してみましたが、大きく変わることはなかったです。
強いていうなら、引数のUIImpactFeedbackGenerator.FeedbackStyleの場合は、「.heavy
 .light .medium .rigid .soft」の5つの引数から触覚のスタイルを変更することができます。

#### 【UIImpactFeedbackGenerator】コード例

```UIImpactFeedbackGenerator.Swift

    /// ポイント③ 
    func  communicateNotificationtWith(type: UIImpactFeedbackGenerator.FeedbackStyle) {
        let generator = UIImpactFeedbackGenerator(style: type)
        generator.prepare()
        generator.impactOccurred()
    }

    @objc private func longPressMapView() {
        /// ポイント④
        communicateNotificationtWith(type: .heavy)
    }

```
##### コード解説
- ポイント③ポイント④
どちらもUINotificationFeedbackGeneratorの実装時のコードとあまり変わりませんので、特に新しいことは解説しません。1点だけ異なることがあります。それは、引数のUIImpactFeedbackGenerator.FeedbackStyleを使用しているということです。
先にも解説していたように5つの選択肢がありますので、挙動に合わせてご自身で細かく触覚のスタイルを変更することができます。

## おまけ
Appleの公式リファレンスには、おまけ程度にさらっと、**フィードバックを与える際の注意点** として以下の3点が述べられています。
- 常に意図を持ったフィードバックを使用し、触覚機能の使用を目的にしない。要するに、フィードバックはユーザーに何かを伝えるための手段であるだけで、目的にしない。
- 触覚フィードバックを伝える動作の対象は、ユーザーに対して明確である必要がある。具体的にその対象は、目に見える変化が起きたタイミングもしくは、ユーザーの挙動に対応すべきです。フィードバックは何もないところには使用しない。
- フィードバックは使いすぎない。使用しすぎるとユーザーを困惑させたり、本来知らせるべきフィードバックのサインも薄れてフィードバックの機能が有効でなくなります。

上記は、Appleのリファレンスを参考に全て僕が若干意訳していますが、総じてフィードバックの「無意味な使用・多用」を行わないことがベースであることを説明しています。
より詳しい解説が必要な方は、以下の参考文献にもある**『Playing haptics』** を確認いただければより深い理解が得られると思います！


## さいごに
画面の見た目やアプリの使いやさ等でUXを向上させようと考えていましたが、触覚機能を使ってユーザーに情報を伝えるという考えが盲点でした。
UI/UXを向上させるためにまだまだできることはありそうなので、また学んだことがあれば共有したいと思います！


間違いや、UIImpactFeedbackGeneratorとUINotificationFeedbackの大きな違いがあれば、コメントで教えていただければありがたいです！

## 参考文献
Apple公式のリファレンス
【UIImpactFeedbackGenerator】

https://developer.apple.com/documentation/uikit/uiimpactfeedbackgenerator

【UINotificationFeedback】

https://developer.apple.com/documentation/uikit/uinotificationfeedbackgenerator

【Using feedback generators】

https://developer.apple.com/documentation/uikit/uifeedbackgenerator#2555399

【Playing haptics】

https://developer.apple.com/design/human-interface-guidelines/patterns/playing-haptics