iOS 7 では、Apple は新しいデフォルトのナビゲーション動作を追加しました。画面の左端からスワイプして、ナビゲーション スタックに戻ることができます。しかし、私のアプリでは、この動作はカスタムの左メニューと競合します。では、UINavigationController でこの新しいジェスチャーを無効にすることは可能ですか?
18 に答える
私は解決策を見つけました:
目的 C:
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
スウィフト 3+:
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
ジェスチャーを無効に設定しても、常に機能するとは限らないことがわかりました。それは機能しますが、私にとっては、一度バックジェスチャを使用した後にのみ機能しました。2 回目は、バックジェスチャをトリガーしません。
私にとっての修正は、ジェスチャーを委任し、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;
}
次の理由により、Twanの回答を少し改良しました。
- あなたのView Controllerは他のジェスチャーレコグナイザーへのデリゲートとして設定されるかもしれません
- デリゲートを に設定する
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;
}
スイフトの場合:
navigationController!.interactivePopGestureRecognizer!.enabled = false
iOS 10以降で動作します:
- (void)viewWillAppear:(BOOL)animated {
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
}
viewDidLoad() メソッドでは機能しません。
私の方法。すべてを支配する 1 つのジェスチャ認識機能:
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
これらのソリューションはすべて、推奨されていない方法で Apple のジェスチャ認識機能を操作します。私は友人から、より良い解決策があると言われました:
[navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail: myPanGestureRecognizer];
myPanGestureRecognizer は、たとえばメニューを表示するために使用しているジェスチャ認識エンジンです。そうすれば、新しいナビゲーション コントローラーを押したときに Apple のジェスチャ認識機能が再びオンになることはありません。また、電話がスリープ状態になっている場合や負荷が高い場合に発生する可能性のあるハック遅延に頼る必要もありません。
次に必要になったときに覚えていないことがわかっているので、ここに残しておきます。問題の解決策がここにあります。
与えられた回答はどれも、問題の解決に役立ちませんでした。ここに私の答えを投稿してください。誰かの役に立つかもしれません
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!)
}
}
これにより、iOS v8.x以降でスワイプバックが無効になります
これviewDidLoad:
は iOS 8 で機能します。
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