2010-05-12 16 views
5

Tengo la opinión de que al recibir doble toque, envía una notificación al controlador raíz, que a su vez quita y libera la vista.Objeto desasignado que recibe el mensaje UIGestureRecognizer

El problema es que una vez que se ha liberado la vista, recibe otro evento GestureRecognizer retrasado.

A continuación se presenta la información de 'instrumentos':

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 parece que sea lanzado en el momento correcto.

La pregunta es por qué está llegando este evento de gesto adicional.

+0

¿Alguna respuesta desde entonces? Tengo el mismo problema – CedricSoubrie

Respuesta

0

Los gestos retardados, por definición, se envían después de un pequeño retraso. Esto (UIScrollViewDelayedTouchesBeganGestureRecognizer) se utiliza para garantizar que los gestos de pellizco y panorámica obtengan una mayor prioridad.

Un reconocedor de gestos no conservará su estado para evitar un ciclo de retención. Por lo tanto, cuando este reconocedor dispara, lo enviará a una vista desasignada.

Puede retrasar el -release de la vista (por ejemplo, con -performSelector:withObject:afterDelay:). O en lugar de eliminar la vista, simplemente puede configurarlo hidden.

+0

Gracias por la respuesta. Considero que ambas opciones suenan un poco como soluciones incorrectas (sin ofender ...). ¿No hay una forma de decirle a los reconocedores de gestos que eliminen todos los mensajes pendientes? Ya he intentado llamar a 'removeTarget' en el reconocedor de gestos y 'removeGestureResognixer' en la vista, pero todavía no tuve suerte. –

+0

@LK: ¿Intentó configurar '.gestureRecognizers' en nil? – kennytm

+0

En realidad no lo resolvió ... Incluso con un retraso estoy obteniendo esto. –

7

No sé si tenía exactamente el mismo problema, pero aquí es cómo lo hice por la mía:

1- Enable Zombie mode en Xcode para obtener un mensaje preciso con el fin de asegurarse de que está buscando en la correcta lugar. Después de que obtendrá un mensaje como este: [vista general gestureRecognizerFailed:]: mensaje enviado a la instancia desasignado 0x53d6d00

2- Ahora que se conoce el problema exacto, gestos desactivarlo en este objeto antes de extraerla:

// 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; 

Esto debería hacer el truco.

[EDITAR] Otra solución que funcionó para mí: No utilice 'liberación automática' para reconocedores de gestos. En la mayoría de los casos, puede liberar directamente el reconocedor después de agregarlo a una vista.

+0

Si los usa como IBOutlets, asegúrese de que sean débiles y luego anule la propiedad una vez que haya terminado de usarla si es necesario. Igual que la edición anterior pero puede no ser obvia para algunos. – cynistersix

0

¿hay algo malo con simplemente hacer esto:

if (gestureRecognizer) { 
    if ((touch.view == UIButtonTypeCustom)) { 
     return NO; 
    } 
    return YES; 
} else return NO; 
2

Parece que el reconocedor gesto es el envío de una devolución de llamada a su controlador después de que su controlador ha sido desasignado. Asegúrese de quitar su reconocedor de gestos de la vista a la que lo conectó antes de desasignar su controlador.

En su clase controlador, es probable que configurar su gesto reconocedor algo como esto:

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

Así que asegúrese de eliminar el reconocedor gesto en el método dealloc de su controlador:

- (void)dealloc { 
    [_view removeGestureRecognizer:_doubleTapGestureRecognizer]; 
    [_doubleTapGestureRecognizer release]; 
    [_view release]; 
    [super dealloc]; 
} 
0

He aquí un solución obvia de cómo lo resolví ... asegúrese de lanzar su vista real.Mi vista tenía un montón de subvistas que estaba lanzando pero no revelé mi visión real. Después de que lo hice, el programa estaba bien.

Cuestiones relacionadas