IOS 7では、Appleは新しいデフォルトのナビゲーション動作を追加しました。ナビゲーションスタックに戻るには、画面の左端からスワイプすることができます。しかし私のアプリでは、この動作は私のカスタム左メニューと衝突します。それで、UINavigationControllerでこの新しいジェスチャーを無効にすることは可能ですか?
私は解決策を見つけました:
Objective-C:
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
Swift 3:self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
ジェスチャーを無効に設定するだけではうまくいかないことがわかりました。それは動作しますが、私にとってはそれは私がかつて裏表紙を使用した後にのみ行われました。二度目はそれが裏切りを誘発しないでしょう。
私の解決策は、ジェスチャーを委任し、NOを返すようshouldbeginメソッドを実装することでした。
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Disable iOS 7 back gesture
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// Enable iOS 7 back gesture
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
}
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
return NO;
}
NavigationControllerからジェスチャレコグナイザを削除するだけです。 iOS 8で動作します。
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
[self.navigationController.view removeGestureRecognizer:self.navigationController.interactivePopGestureRecognizer];
IOS 8以降、承認された回答は機能しません。私はメインのゲーム画面でジェスチャーを消すためにスワイプを止める必要がありました。
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
}
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
return NO;
}
Twanの答えを少し洗練しました。
nil
に設定すると、ルートビューコントローラに戻って他の場所に移動する前にスワイプジェスチャをするときに問題が発生します。次の例ではiOS 7を想定しています。
{
id savedGestureRecognizerDelegate;
}
- (void)viewWillAppear:(BOOL)animated
{
savedGestureRecognizerDelegate = self.navigationController.interactivePopGestureRecognizer.delegate;
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}
- (void)viewWillDisappear:(BOOL)animated
{
self.navigationController.interactivePopGestureRecognizer.delegate = savedGestureRecognizerDelegate;
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer == self.navigationController.interactivePopGestureRecognizer) {
return NO;
}
// add whatever logic you would otherwise have
return YES;
}
これをroot vcに設定してください。
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:YES];
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
-(void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:YES];
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}
Swiftの場合:
navigationController!.interactivePopGestureRecognizer!.enabled = false
特定のナビゲーションコントローラのスワイプバック機能を管理したい場合は、 SwipeBack の使用を検討してください。
これでnavigationController.swipeBackEnabled = NO
を設定できます。
例えば:
#import <SwipeBack/SwipeBack.h>
- (void)viewWillAppear:(BOOL)animated
{
navigationController.swipeBackEnabled = NO;
}
それは CocoaPods を通してインストールすることができます。
pod 'SwipeBack', '~> 1.0'
説明不足のため申し訳ありません。
それはIOS 10以降で私のために働く:
- (void)viewWillAppear:(BOOL)animated {
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
}
viewDidLoad()メソッドでは動作しません。
私の方法それらすべてを統制するためのジェスチャー認識機能
class DisabledGestureViewController: UIViewController: UIGestureRecognizerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
navigationController!.interactivePopGestureRecognizer!.delegate = self
}
func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
// Prevent going back to the previous view
return !(navigationController!.topViewController is DisabledGestureViewController)
}
}
重要:ナビゲーションスタックのどこにもデリゲートをリセットしないでください。navigationController!.interactivePopGestureRecognizer!.delegate = nil
これはSwift 3のやり方です
私のために働く
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
これらのソリューションはすべて、推奨しない方法でAppleのジェスチャ認識機能を操作します。私は友人からもっと良い解決策があると言われました:
[navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail: myPanGestureRecognizer];
myPanGestureRecognizerは、あなたが使用しているジェスチャレコグナイザです。あなたのメニューを見せてください。そうすれば、新しいナビゲーションコントローラをプッシュしてもAppleのジェスチャレコグナイザはそれらの機能を有効にすることができず、電話機がスリープ状態になったり重い負荷がかかった場合に早すぎる発火を招くことがあります。
次回必要になったときにこれを覚えていないことがわかっているので、ここに残しておきます。その後、ここで問題の解決策を見つけます。
これはiOS 8のviewDidLoad:
で動作します。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.navigationController.interactivePopGestureRecognizer.enabled = false;
});
多くの問題は古き良きdispatch_after
の助けを借りて解決することができます。
この解決策は潜在的に危険であることに注意してください、あなた自身の推論を使ってください。
IOS 8.1の場合、遅延時間は0.5秒です。
IOS 9.3では、これ以上遅延は必要ありません。これをviewDidLoad
に配置するだけで機能します。
(iOS 9.0-9.3で動作する場合は未定)
navigationController?.interactivePopGestureRecognizer?.enabled = false
与えられた答えのどれも私が問題を解決するのを助けませんでした。私の答えをここに投稿してください。誰かに役立つかもしれません
あなたのviewcontrollerでグローバル変数としてprivate var popGesture: UIGestureRecognizer?
を宣言してください。それからviewDidAppearとviewWillDisappearメソッドでコードを実装
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if self.navigationController!.respondsToSelector(Selector("interactivePopGestureRecognizer")) {
self.popGesture = navigationController!.interactivePopGestureRecognizer
self.navigationController!.view.removeGestureRecognizer(navigationController!.interactivePopGestureRecognizer!)
}
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
if self.popGesture != nil {
navigationController!.view.addGestureRecognizer(self.popGesture!)
}
}
これにより、iOSv8.x以降ではスワイプバックが無効になります
Swift 4の場合、これは機能します。
class MyViewController: UIViewController, UIGestureRecognizerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.interactivePopGestureRecognizer?.gesture.delegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.navigationController?.interactivePopGestureRecognizer?.gesture.isEnabled = false
}
}
それは私にとってほとんどのビューコントローラでうまくいきました。
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
UIPageViewControllerのようないくつかのビューコントローラでは動作しませんでした。以下のUIPageViewControllerのpagecontentviewcontrollerコードは私のために働きました。
override func viewDidLoad() {
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
self.navigationController?.interactivePopGestureRecognizer?.delegate = self
}
override func viewWillDisappear(_ animated: Bool) {
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
}
UIGestureRecognizerDelegateでは、
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer == self.navigationController?.interactivePopGestureRecognizer {
return false
}
return true
}