Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deallocated object getting UIGestureRecognizer message

I have a view that on receiving double tap, sends a notification to the root controller, who in turns removes and releases the view.

The problem is that after the view has been released, it receives another delayed GestureRecognizer event.

Following is the info from 'Instruments':

Category        Event Type  RefCt   Timestamp   Address      Size   Responsible Library Responsible Caller
UIScrollView    Zombie          -1  00:06.166   0x55496a0    0                   UIKit  -[UIGestureRecognizer _updateGestureWithEvent:]


   0 CoreFoundation ___forwarding___
   1 CoreFoundation _CF_forwarding_prep_0
   2 UIKit -[UIGestureRecognizer _updateGestureWithEvent:]
   3 UIKit -[UIGestureRecognizer _delayedUpdateGesture]
   4 UIKit _UIGestureRecognizerUpdateObserver
   5 UIKit _UIGestureRecognizerUpdateGesturesFromSendEvent
   6 UIKit -[UIWindow _sendGesturesForEvent:]
   7 UIKit -[UIWindow sendEvent:]
   8 UIKit -[UIApplication sendEvent:]
   9 UIKit _UIApplicationHandleEvent
  10 GraphicsServices PurpleEventCallback
  11 CoreFoundation CFRunLoopRunSpecific
  12 CoreFoundation CFRunLoopRunInMode
  13 GraphicsServices GSEventRunModal
  14 GraphicsServices GSEventRun
  15 UIKit UIApplicationMain
  16 ipadapp main /Users/test/Projects/app/ipadapp/main.m:7
  17 ipadapp start

UIScrollView seems to be released at the correct time.

Question is why this additional gesture event is arriving.

like image 540
LK. Avatar asked May 12 '10 14:05

LK.


2 Answers

I don't know if I had exactly the same problem but here is how I did for mine:

1- Enable Zombie mode in Xcode to get a precise message in order to be sure you are looking at the correct place. After that you will get a message like this : [OverView gestureRecognizerFailed:]: message sent to deallocated instance 0x53d6d00

2- Now that you know the exact problem, desactivate gestures on this object before removing it :

    // I have to remove the gestures, because a GesturerecongizerFailed can arrive after the view has been deallocated
    for (UIGestureRecognizer* gesture in self.overView.gestureRecognizers) {
        NSLog(@"Desactive un gesture");
        gesture.delegate = nil ; 
        gesture.enabled = NO;
    }
    // Remove the view from the display
    [self.overView removeFromSuperview];
    self.overView = nil;

This should do the trick.

[EDIT] Another solution that worked for me : don't use 'autorelease' for gesture recognizers. In most case you can directly release the recognizer after adding it to a view.

like image 85
CedricSoubrie Avatar answered Oct 25 '22 01:10

CedricSoubrie


It looks like your gesture recognizer is sending a callback to your controller after your controller has been deallocated. Make sure you remove your gesture recognizer from the view you attached it to before you deallocate your controller.

In your controller class, you probably set up your gesture recognizer something like this:

- (void)loadView {
    [super loadView];
    _view = [[UIView alloc] init];
    _doubleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_handleDoubleTap:)];
    [_view addGestureRecgonizer:_doubleTapGestureRecognizer];
}

So make sure you remove the gesture recognizer in your controller's dealloc method:

- (void)dealloc {
    [_view removeGestureRecognizer:_doubleTapGestureRecognizer];
    [_doubleTapGestureRecognizer release];
    [_view release];
    [super dealloc];
}
like image 32
nefaurk Avatar answered Oct 25 '22 00:10

nefaurk