Rohith Nandakumar
Rohith Nandakumar

Reputation: 11427

How to disable back gesture in iOS 7 for only one view

I am trying to disable the back gesture for my view controller using the following set of code.

In FirstViewController.m, I'm setting the delegate of interactivePopGestureRecognizer

- (void) viewWillLoad {

    // Other stuff..
    self.navigationController.interactivePopGestureRecognizer.delegate = self;
}

And then implementing the <UIGestureRecognizerDelegate> method and returning NO.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {

     return NO;
}

And in dealloc I'm setting the delegate to nil. (I have read somewhere that in iOS 7, you have to manually set the delegates to nil)

- (void)dealloc {

    self.navigationController.delegate = nil;
    self.navigationController.interactivePopGestureRecognizer.delegate = nil;
}

This works in the FirstViewController. But when I push SecondViewController to this, the gesture does not work on that either. How can I disable the gesture in FirstViewController only?

Also when I pop FirstViewController to go to RootViewController and then try to push FirstViewController again, I get the object deallocated error :

[FirstViewController gestureRecognizer:shouldReceiveTouch:]: message sent to deallocated instance 0x14ed0280

Why else do I need to do other than setting the delegates to nil? Or am I setting it in the wrong place?

Upvotes: 5

Views: 8095

Answers (6)

John Rogers
John Rogers

Reputation: 2192

I originally put these answers into a comment below the accepted answer, but I feel this needs to be said as an answer to get more visibility.

More often than not, you will find that the accepted answer does not work. This is because viewWillAppear: can be called before the view is added to a navigation controller's view hierarchy, and so self.navigationController is going to be nil. Because of this, the interactivePopGestureRecognizer may not be disabled in some cases. You're better off calling it in viewDidAppear: instead.

Here's code that will work (assuming your view controller is correctly added to a navigation controller's view hierarchy):

Objective-C

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [[[self navigationController] interactivePopGestureRecognizer] setEnabled:NO];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [[[self navigationController] interactivePopGestureRecognizer] setEnabled:YES];
}

Swift

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    navigationController?.interactivePopGestureRecognizer?.isEnabled = false
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    navigationController?.interactivePopGestureRecognizer?.isEnabled = true
}

Upvotes: 17

Hesamoy
Hesamoy

Reputation: 301

This just worked for me in xCode 7:

override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        self.navigationController!.interactivePopGestureRecognizer!.enabled = false

}
override func viewWillDisappear(animated: Bool) {
    super.viewDidDisappear(animated)
    self.navigationController!.interactivePopGestureRecognizer!.enabled = true
}

Upvotes: 0

Abuzar Amin
Abuzar Amin

Reputation: 1991

I tried the all above but they did not work for me.So i tried this and it works for me on both IOS7 and IOS8.

Just make sure that your view controller implements this protocol i.e UIGestureRecognizerDelegate and write the code given below.

-(void)viewWillAppear : (BOOL) animated {

[super viewWillAppear : animated];

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {

    self.navigationController.interactivePopGestureRecognizer.enabled =

NO;
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}

}

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

if ([gestureRecognizer isEqual:self.navigationController.interactivePopGestureRecognizer]) {

    return NO;

} else {

    return YES;

}

}

Upvotes: 3

Antoine
Antoine

Reputation: 23976

I found out setting the gesture to disabled only doesn't always work. It does work, but for me it only did after I once used the backgesture. Second time it wouldn't trigger the backgesture. Furthermore, as John Rogers said, it's import to use the viewDidAppear and viewWillAppear as the navigationController else would be nil.

Fix for me was to delegate the gesture and implement the shouldbegin method to return 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;
}

Upvotes: 0

rabenson
rabenson

Reputation: 9

For only one view, I don't know the way... But I use the next code to disable fully the swipe gesture:

in your AppDelegate.m

if ([[UIDevice currentDevice].systemVersion floatValue] >= 7){
        self.navigationController.interactivePopGestureRecognizer.enabled = NO;
    }

Upvotes: -1

Tarek Hallak
Tarek Hallak

Reputation: 18470

Try the below untested code in your FirstViewController :

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

-(void) viewWillDisappear:(BOOL)animated 
{
    [super viewWillDisappear:animated];
    self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}

Upvotes: 24

Related Questions