Posted at

UINavigationControllerのスワイプで戻るを有効・無効にする方法

More than 3 years have passed since last update.

ナビゲーションバーの左にボタンを配置すると「スワイプで戻る」が効かなくなります。


Objective-C

UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"back_button_image"]

style:UIBarButtonItemStylePlain
target:self
action:@selector(backButtonTapped:)];
self.navigationItem.leftBarButtonItem = backButtonItem;

画面が戻る前に特別な処理をしたいなどは戻るボタンの代わりに上記のようにナビゲーションバーの左側に独自実装したボタンを配置する必要があります。

だけど、スワイプで戻る処理はちゃんと実装したい。

そういう時は自前で実装する必要があります。


Objective-C・ViewController.h

@interface ViewController : UIViewController <UIGestureRecognizerDelegate>



Objective-C・ViewController.m

self.navigationController.interactivePopGestureRecognizer.delegate = self;


これでスワイプで戻るが有効になります。

viewDidLoad:viewWillAppear:で呼べば大丈夫。

iOS6には対応していないので、もしサポートする場合は分岐する必要があります。


スワイプで戻るを無効にする方法

逆にスワイプで戻るを無効にする方法はこちら。

常にNOを返せば問題ないですね。

独自のUINavigationControllerクラスでこれを実装すれば問題ないと思います。


Objective-C・ViewController.m

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {

return NO;
}


スワイプで戻るを条件によって有効無効にしたい場合

例えば、編集されていない時にはスワイプで戻るを有効、編集されているときはスワイプで戻るを無効にしたい時は追記でこんな感じで実装。


Objective-C・ViewController.m

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {

// 編集フラグがオンの時はスワイプで戻るを無効
if(self.Edit) {
return NO;
} else {
return YES;
}
}


独自でスワイプで戻るを無効にした状態から元に戻す場合

基本的にiOSのスワイプで戻るが有効の状態で、特別な画面のみ戻るボタンを隠して、独自実装したい場合。

こういうパターンですね。

画面1

↓ ↑
画面2
↓ ↑
画面3
ナビゲーションバーの左ボタンを独自実装
self.navigationController.interactivePopGestureRecognizer.delegateを設定
↓ ↑
画面4

画面2から画面1へ戻る時にスワイプで戻るがなぜか効かなくなります。

画面3でself.navigationController.interactivePopGestureRecognizerを実装しているので、その名残が残っているわけですね。

なので、その場合はこういう形で実装します。


Objective-C・ViewController.m

- (void)viewWillAppear:(BOOL)animated {

self.navigationController.interactivePopGestureRecognizer.delegate = self;
}

- (void)viewWillDisappear:(BOOL)animated {
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
}


ポイントはnilにするタイミングをviewWillDisappear:にするというところ。

viewDidDisappear:でnilにしても効いてくれないので、画面が閉じられる前に実装。

(特に一番最後のパターンをしたくて)かなり躓いたので、お役に立てればと思います。