Remove UIGestureRecognizer from view

I just had some “fun” searching for a UIGestureRecognizer leak. Basically a UIGestureRecognizer leak will manifest in a BAD EXEC (message send to dealloced instance).

TD;DR

Make sure you always remove a UIGestureRecognizer from the view it is actually attached to:

[self.gestureRecognizer.view removeGestureRecognizer:self.gestureRecognizer];

Long version

If you never had any trouble with UIGestureRecognizer leaks you probably do it like this:

//...
@property (strong, nonatomic) UIPanGestureRecognizer *panGestureRecognizer;
// ...
- (void)viewDidLoad { 
//...
self.panGestureRecognizer = [[UIPanGestureRecognizer alloc]
//...
}
- (void)viewDidAppear:(BOOL)animated {
//...
[self.someView addGestureRecognizer:self.panGestureRecognizer];
// ...
}
- (void)viewWillDisappear:(BOOL)animated {
//...
[self.someView removeGestureRecognizer:self.panGestureRecognizer];
//...
}
- (void)dealloc {
//...
self.panGestureRecognizer.delegate = nil;
self.panGestureRecognizer = nil;
//...
}

The above code will actually work most times.

Problem

There are a few cases where it will not work and it is not obvious why. The problem is that the above code requires self.someView to be constant. If self.someView does not reference the same view as it did when self.panGestureRecognizer was added, then the method does actually nothing … and voilà: a leak.

Solution

It is much safer to do:

[self.panGestureRecognizer.view removeGestureRecognizer:self.panGestureRecognizer];

That way you can be sure that you always remove the UIGestureRecognizer from the correct view.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.