【iOS】アクセシビリティ(VoiceOver)対応チートシート

# 目次
- [はじめに](#はじめに)
- [読み上げテキストの設定](#読み上げテキストの設定)
- [accessibilityTraitsの指定と読み方](#accessibilitytraitsの指定と読み方)
- [意図しない読み方がされた時の対処法](#意図しない読み方がされた時の対処法)
- [フォーカス順序を変えたい](#フォーカス順序を変えたい)
- [ユーザーのアクションをきっかけにフォーカスを変えたい](#ユーザーのアクションをきっかけにフォーカスを変えたい)
- [デバッグ用の便利設定](#デバッグ用の便利設定)
- [さいごに](#さいごに)

# はじめに
iOSアプリでVoiceOver対応を行なったので、その知見をまとめました。(今後も随時更新していきます。)
VoiceOverについての詳細は、[Appleのアクセシビリティに関するページ](https://www.apple.com/jp/accessibility/vision/)をご覧ください。

# 読み上げテキストの設定
VoiceOverの読み上げテキストは以下の方法でシンプルに設定できます。
```
self.titleLabel.accessibilityLabel = "アクセシビリティ用の読み上げテキスト"
```
UILabelに限らず、UIButtonやUIImage、UIView、UIControl等も同様の方法で指定します。

ただし、UISwitchやCollectionViewのCell等、値を保持しているコンポーネントについては、
`accessibilityValue`という別の項目を使用する必要があるので注意が必要です。

※UIViewやUIControl等の一部のコンポーネントは**デフォルトでフォーカスが当たらない場合がある**ので、以下の方法でアクセシビリティの要素として認識する様にしてください。
```
self.contentView.isAccessibilityElement = true
```

# accessibilityTraitsの指定と読み方
`accessibilityTraits`とは、**その要素が何を示しているのか**端的に示すものです。
この機能はユーザーに次の行動を促す上で、非常に重要な役割を担っています。

例えば以下の様に指定した場合、editButtonは「編集ボタン」と読まれる様になり、
この要素がボタンでありタップできる事をユーザーに伝えることが出来ます。

```
self.editButton.accessibilityLabel = "編集"
self.editButton.accessibilityTraits = .button
```

以下に代表的な`accessibilityTraits`と、実際に読み上げられるテキストをまとめます。
（iPhoneの言語設定を日本語or英語に設定した場合）
| accessibilityTraits | 日本語 | 英語 |
|:-----------|:------------|:------------|
| image | イメージ | image |
| button | ボタン | button |
| header | 見出し | header |
| link | リンク | link |

UIButtonの様にデフォルトでaccessibilityTraitsが設定されているコンポーネントもあるので、
値の変更や追加したい場合に上記の方法を活用してみてください。

# 意図しない読み方がされた時の対処法
様々な画面でVoiceOver対応をしていると、読み上げが意図した通りにされない事がよくあります。
私が苦戦したものをいくつかピックアップしますので、実装の参考になれば幸いです。

**Q1. 日付、時刻の読み上げが上手く出来ない**
「6月11日(土)」や「12:00」等、日付や時刻の読み上げはそのままでは上手くいかないケースが多いです。曜日は「土(つち)」「水(みず)」、時刻は「12:00(じゅうに)」と読まれてしまいます。

**A1.頑張ってロジックを書いた**
 曜日については数が少ないので、個別に文言を設定することで対応しました。時刻についても、少しロジックを書いて「○時○分」と読ませる対応をしました。(":"でsplitして0埋めして...等)
対応しているアプリは意外と少ないですが、日付や時刻はかなり重要な情報なので、対応したい部分ですね。繰り返し出てくる処理なので、Formatterの様なものを作っておくと便利です。

**Q2.2単語が連続して読み上げられる**
「うまい棒 コーンポタージュ味」と読ませたいが、実際の読み上げは「うまい棒コーンポタージュ味」の様に繋げて読まれてしまう。

**A2. カンマや句読点を使う**
「うまい棒、コーンポタージュ味」と指定すると、少し間を置いて読んでくれます。

**Q3.英単語を1文字ずつ読ませたい**
「IAEA」を読み上げさせると、「いあいえ」の様に読まれてしまう。

**A3.スペースを開ける、もしくはひらがな指定する**
「I A E A」もしくは「あいえーいーえー」と指定すると正しく読まれます。

**Q4.一部の記号が読まれない**
文字列の中に「-(ハイフン)」が含まれていると、そこだけ何故か読み上げられない。

**A4.読み上げられない記号は変換する**
「-(ハイフン)」など一部の記号はデフォルトでは読み上げられません。
「-(ハイフン)」を「ハイフン」という文字列に変換してテキストに設定する必要があります。
こちらも繰り返し出てくる処理なので、Formatterの様なものを作っておくと便利です。

# フォーカス順序を変えたい
VoiceOverモードの状態でスワイプ操作をすると、次の要素にフォーカスが当たります。
ここではフォーカスが当たる順序を変更する方法を記載します。

下記の様に`accessibilityElements`の中にフォーカスを当てたい順番で要素を入れてあげればOKです。
```
self.accessibilityElements = [self.titleLabel, self.detailLabel, self.okButton]
```
この場合、`titleLabel`→`detailLabel`→`okButton`の順番にフォーカスが当たります。

# ユーザーのアクションをきっかけにフォーカスを変えたい
ユーザーの「ボタンを押す」等のアクションをきっかけにフォーカスを意図した要素に当てたい場合は、以下の方法を用います。

```
UIAccessibility.post(notification: .layoutChanged, argument: self.titleLabel)
```
ボタンを押した時に呼ばれるメソッドに上記のコードを書いておけば、argumentで指定したコンポーネントにフォーカスを当てられます。

これにより、「ユーザーが入力を行ったら次の要素にフォーカスを移動させる」等も簡単に実現できます。

# デバッグ用の便利設定
VoiceOverの開発を行う場合に便利な設定です。どれも効率的な開発に欠かせないものなので、ぜひ活用してみてください。

**ショートカットの設定**
iPhoneの「設定」 > 「アクセシビリティ」　> 「ショートカット」でVoiceOverを設定しておくと、電源ボタントリプルタップでVoiceOverのON/OFFが切り替えられます。

**読み上げテキストを画面に表示する**
iPhoneの「設定」 > 「アクセシビリティ」　> 「音声コントロール」で音声コントロールをONに設定して、「オーバーレイ」を「項目名」にする事で、設定した読み上げテキストがアプリの画面上に表示される様になります。
VoiceOverをオンにしなくても設定した文言が確認できるので、かなり便利です。

**読み上げ速度の設定**
iPhoneの「設定」 > 「アクセシビリティ」　> 「VoiceOver」で「読み上げ速度」を最大まで調整すると、動作確認できるスピードが上がります。またこの画面から「読み上げの声」も変更できるので、お好みの声を選択してみてください。
![IMG_0748.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793562/d58462a8-8ae6-2107-9c46-32b1f4a1f238.png)

**Accessibility Inspectorを使用してシミュレータで読み上げ設定を確認する**
Xcodeのツールバーの「Xcode」　 > 「Open Developer Tool」 > 「Accessibility Inspector」で使えます。
実機に繋げず、シミュレータで読み上げテキストを確認したい場合に便利なツールです。

**キーボードを使用する際のショートカット**
キーボード操作でVoiceOverを使用する場合は、以下のショートカット集が参考になります。
https://support.apple.com/ja-jp/HT204434

**VoiceOver対応関連の記事**
- [UIAccessibility(Apple公式)](https://developer.apple.com/documentation/objectivec/nsobject/uiaccessibility)
- [noteのiOSアプリで実装したアクセシビリティの全て](https://fromkk.me/n/n2dbeb54cdf0d)
- [はじめての VoiceOver 対応](https://qiita.com/RyoAbe/items/c111dd9349b6ff67b558)

# さいごに
アクセシビリティ(VoiceOver)対応は慣れるまで、操作や実装に苦慮する部分もありますが、多くのユーザーにとってより使いやすいアプリを目指す上では欠かせない機能です。
アプリにVoiceOver対応を導入する上で、私の記事が参考になれば幸いです。