先に結論
-
modalPresentationStyle = .pageSheet
かつisModalInPresentation = false
の場合はスクラブジェスチャでモーダルをdismiss - それ以外(多分)はpopして、popするものがなくなったら
accessibilityPerformEscape()
を見に行く。
accessibilityPerformEscape
そもそもaccessibilityPerformEscape()
とは...
VoiceOverがオンのときに、二本指のスクラブジェスチャ(二本指でZを描くようなジェスチャ)によって、モーダル(もしくは階層)を閉じるためのメソッドであり、アクセシビリティ要素が特定の動作をサポートするためのメソッド群UIAccessibilityAction
一つらしいです。
accessibilityPerformEscape()
の中にスクラブジェスチャによって発火させたい処理(閉じる系以外の処理以外は書かない方が無難ですね)を書くと、スクラブジェスチャによって画面を閉じたり戻したりできます。
試しにVoiceOverを起動して適当なアプリ(SettingsとかSafariとか)を開いてスクラブジェスチャしてみると、popしたりdismissしたりします。
ドキュメント↓
UINavigationControllerにおけるスクラブジェスチャのデフォルト挙動
ところで、ドキュメントによるとaccessibilityPerformEscape()
のデフォルト実装は戻り値としてfalse
を返すようです。
この戻り値は、モーダルが正常に閉じられたかどうかなので、false
を返すということは中身は空ということじゃないのかなと思います。
なんですけど、UINavigationController
は何も実装していなくても普通にスクラブジェスチャ効くんですよね、よくわからん。誰か詳しい人教えてください。
というわけで、accessibilityPerformEscape()
をoverrideする上でUINavigationController
のデフォルトの挙動に準じた動作をさせられるように、挙動を知っておくことは有意義だと思って色々触ってみたわけです。
試しに以下のような階層のアプリを作りました。
VC1, VC2, NavではそれぞれaccessibilityPerformEscape()
をoverrideしてdismissするようにしています。
- VC1
- Nav
- VC2
- VC3
- Nav
ここで、VC3を開いた状態からスクラブジェスチャを複数回行うことでNavのmodalPresentaitonStyle
とmodalInPresentation
を変更してそれぞれどんな挙動をするか、どのaccessibilityPerformEscape
が呼ばれるのかを確認してみました。
以下の表が結果です
modalPresentationStyle | modalInPresentaion | 挙動 | 呼ばれたaccessibilityPerformEscape() |
---|---|---|---|
.pageSheet | true | VC3 -> VC2 -> VC1 | VC2 -> VC1 のタイミングで VC2のメソッドが呼ばれる |
.pageSheet | false | VC3 -> VC1に遷移 | - |
.fullscreen .formSheet .popOver |
true / false | VC3 -> VC2 -> VC1 | VC2 -> VC1 のタイミングで VC2のメソッドが呼ばれる |
他にもmodalPresentationStyle
は定義されていますが、.pageSheet
以外変化ないので面倒になって確認していません。(誰か...)
多分同じということにしておきましょう!!