web-dev-qa-db-fra.com

Comment désactiver le geste de balayage arrière dans UINavigationController sur iOS 7

Dans iOS 7, Apple a ajouté un nouveau comportement de navigation par défaut. Vous pouvez faire glisser votre doigt depuis le bord gauche de l'écran pour revenir sur la pile de navigation. Mais dans mon application, ce comportement est en conflit avec mon menu de gauche personnalisé. Alors, est-il possible de désactiver ce nouveau geste dans UINavigationController?

318
ArtFeel

J'ai trouvé une solution:

Objective-C:

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
    self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}

Swift 3:
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false

570
ArtFeel

J'ai découvert que régler le geste sur désactivé ne fonctionnait pas toujours. Cela fonctionne, mais pour moi, cela n'a fonctionné qu'après avoir utilisé le backgesture. Deuxième fois, cela ne déclencherait pas le backgesture.

Fix pour moi était de déléguer le geste et d'implémenter la méthode shouldbegin pour renvoyer NO:

- (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;
}
46
Antoine

Il suffit de supprimer la reconnaissance de geste de NavigationController. fonctionne sous iOS 8.

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
    [self.navigationController.view removeGestureRecognizer:self.navigationController.interactivePopGestureRecognizer];
28
Vladimir Samoylov

Depuis iOS 8, la réponse acceptée ne fonctionne plus. Je devais arrêter le glissement pour rejeter le geste sur mon écran de jeu principal afin de mettre en œuvre ceci:

- (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;
}
22
Charlie Seligman

J'ai affiné un peu la réponse de Twan, parce que:

  1. votre contrôleur de vue peut être défini en tant que délégué à d'autres dispositifs de reconnaissance de mouvements
  2. définir le délégué sur nil entraîne des problèmes de blocage lorsque vous revenez dans le contrôleur de vue racine et faites un geste de balayage avant de naviguer ailleurs.

L'exemple suivant suppose 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;
}
20
Ja͢ck

Veuillez définir ceci dans la racine 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;
}
10
reza_khalafi

Pour Swift:

navigationController!.interactivePopGestureRecognizer!.enabled = false
8
iPhone 7

cela fonctionne pour moi dans iOS 10 et plus tard:

- (void)viewWillAppear:(BOOL)animated {
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.enabled = NO;
    }

}

cela ne fonctionne pas sur la méthode viewDidLoad ().

5
Logic

MODIFIER

Si vous souhaitez gérer la fonctionnalité de balayage arrière pour des contrôleurs de navigation spécifiques, envisagez d'utiliser SwipeBack .

Avec cela, vous pouvez définir navigationController.swipeBackEnabled = NO.

Par exemple:

#import <SwipeBack/SwipeBack.h>

- (void)viewWillAppear:(BOOL)animated
{
    navigationController.swipeBackEnabled = NO;
}

Il peut être installé via CocoaPods .

pod 'SwipeBack', '~> 1.0'

Je m'excuse pour le manque d'explication.

5
devxoul

Toutes ces solutions manipulent la reconnaissance des gestes d’Apple d’une manière qu’elles déconseillent. Un ami vient de me dire qu'il existe une meilleure solution:

[navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail: myPanGestureRecognizer];

où myPanGestureRecognizer est la reconnaissance de geste que vous utilisez, par exemple. montrez votre menu. De cette façon, la reconnaissance gestuelle d’Apple ne les réactive pas lorsque vous appuyez sur un nouveau contrôleur de navigation et vous n’aurez pas à vous fier aux retards de piratage qui risquent de se déclencher trop tôt si votre téléphone est mis en veille ou sous une charge importante.

Laissant ceci ici parce que je sais que je ne m'en souviendrai pas la prochaine fois que j'en aurai besoin, puis j'aurai la solution au problème ici.

3
uliwitness

Ma méthode Un identificateur de geste pour les gouverner tous:

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)
    }
}

Important: ne réinitialisez le délégué nulle part dans la pile de navigation: navigationController!.interactivePopGestureRecognizer!.delegate = nil

3
SoftDesigner

C'est le chemin sur Swift 3

travaille pour moi

    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
3
Tayo119

Cela fonctionne dans viewDidLoad: pour 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;
  });

Beaucoup de problèmes pourraient être résolus avec l'aide du bon vieux dispatch_after.

Bien que cette solution soit potentiellement dangereuse, veuillez utiliser votre propre raisonnement.

Mise à jour

Pour iOS 8.1, le délai devrait être de 0,5 seconde

Sur iOS 9.3, plus aucun délai n'est nécessaire, cela fonctionne simplement en plaçant ceci dans votre viewDidLoad:
(À déterminer si cela fonctionne sur iOS 9.0-9.3)

navigationController?.interactivePopGestureRecognizer?.enabled = false
2
Dannie P

Aucune des réponses données ne m'a aidé à résoudre le problème. Afficher ma réponse ici; peut être utile pour quelqu'un

Déclarez private var popGesture: UIGestureRecognizer? comme variable globale dans votre contrôleur de vue. Puis implémentez le code dans les méthodes viewDidAppear et 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!)
    }
}

Cela désactivera le balayage dans iOS v8.x

2
Augustine P A

Pour Swift 4 cela fonctionne:

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
    }

}
1
Mat0

Cela a fonctionné pour moi pour la plupart des viewcontrollers.

self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false

Cela ne fonctionnait pas pour certains contrôleurs de vues comme UIPageViewController. Sur le code pagecontentviewcontroller ci-dessous de UIPageViewController, le code a fonctionné pour moi.

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
}

Sur UIGestureRecognizerDelegate,

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
   if gestureRecognizer == self.navigationController?.interactivePopGestureRecognizer {
      return false
}
      return true
}
0
Faris Muhammed