iOS
UIKit

iOSアプリの「スワイプで戻る」を特定の画面でのみ無効にさせたい場合

More than 1 year has passed since last update.

「スワイプで戻る」を無効にした方が良い画面

iOSアプリはデフォルトで、画面左端をスワイプする(pop gesture)ことで1つ前のViewControllerに戻ることができます。
これは便利なのですが、ドラッグジェスチャを仕込んでいるような画面、例えば「お絵描きペンツール画面」などにおいては、このジェスチャが誤発動する可能性があるため、無効にした方が良さそうです。

戻るジェスチャを無効にする方法

基本

まず、あの「スワイプで戻るジェスチャ」は、誰が管理しているのかと言うと、UINavigationControllerになります。
UINavigationControllerinteractivePopGestureRecognizer: UIGestureRecognizer?というプロパティがあります。

これを無効にすれば良いので、「戻るジェスチャを無効にしたいViewController」のviewDidAppear辺りで、以下のような実装をすればよいです。

self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false

これでOKといえばOKなのですが…。

各ViewControllerで各々やることの問題点

上記の実装を、「戻るジェスチャを無効化したいViewController」でそれぞれ行うのは、あまり良くないです。

  • 有効に戻し忘れてはいけない
  • 無効な画面が2つ以上連続する場合とか、「falseにする」「trueにする」タイミングを慎重に検討しないといけない

これらがあるので、出来れば個々に実装するのはやめて、ズバッと一気に対応したい。

UINavigationControllerDelegate で対応すれば良い

以下の方法で実装することをおすすめします。

  • UINavigationControllerDelegatenavigationController(_:didShow:animated:)のタイミングで処理
  • 「表示された子ViewController」が「戻るジェスチャを無視するべき」なのか否かをチェックし、その結果を反映

予め「戻るジェスチャを無視するべき」を意味するプロトコルを定義しておきます。

protocol NonSwipeable {}

戻るジェスチャを無視したいViewControllerは、このプロトコルに準拠させます。

あとは、UINavigationControllerDelegateで以下の処理を行えばOK。

func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
    navigationController.interactivePopGestureRecognizer?.isEnabled = !(viewController is NonSwipeable)
}

こうしておけば、普通の画面(戻るジェスチャは有効であるべき)に遷移した際に、ちゃんとジェスチャを有効に戻してくれます。