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?
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
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;
}
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];
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;
}
J'ai affiné un peu la réponse de Twan, parce que:
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;
}
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;
}
Pour Swift:
navigationController!.interactivePopGestureRecognizer!.enabled = false
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 ().
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.
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.
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
C'est le chemin sur Swift 3
travaille pour moi
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
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.
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
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
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
}
}
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
}