2010-05-12 16 views
5

Ho la vista che alla ricezione di un doppio tocco, invia una notifica al controller di root, che a sua volta rimuove e rilascia la vista.Oggetto deallocated che riceve il messaggio UIGestureRecognizer

Il problema è che dopo che la vista è stata rilasciata, riceve un altro evento GestureRecognizer ritardato.

seguito è le informazioni da 'strumenti':

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 sembra per essere rilasciato al momento giusto.

Domanda è perché questo evento gesto aggiuntivo sta arrivando.

+0

Qualche risposta da allora? Ho lo stesso problema – CedricSoubrie

risposta

0

I movimenti ritardati, per definizione, vengono inviati dopo un breve ritardo. Questo (UIScrollViewDelayedTouchesBeganGestureRecognizer) viene utilizzato per garantire che i gesti pizzico e panoramica abbiano una priorità più alta.

Un riconoscitore di gesti non mantiene il proprio stato per evitare un ciclo di mantenimento. Quindi, quando questo riconoscimento viene attivato, invierà a una vista deallocata.

È possibile ritardare lo -release della vista (ad esempio con -performSelector:withObject:afterDelay:). O invece di rimuovere la vista, è sufficiente impostarla su hidden.

+0

Grazie per la risposta. Trovo che entrambe le tue opzioni sembrino un po 'come soluzioni alternative (senza offesa ...) - non c'è un modo per dire ai riconoscitori di gesti di eliminare tutti i messaggi in attesa? Ho già provato a chiamare 'removeTarget' sul riconoscimento dei gesti e 'removeGestureResognixer' sulla vista ma ancora senza fortuna. –

+0

@LK: Hai provato a impostare '.gestureRecognizers' su zero? – kennytm

+0

In realtà non l'ho risolto ... Anche con un ritardo sto ricevendo questo. –

7

Non so se ho avuto esattamente lo stesso problema, ma ecco come ho fatto per la mia:

1- Enable Zombie mode in Xcode per ottenere un messaggio preciso, al fine di essere sicuri che si sta guardando il corretto posto. Dopo di che si otterrà un messaggio come questo: [Panoramica gestureRecognizerFailed:]: messaggio inviato ad esempio deallocato 0x53d6d00

2- Ora che si conosce il problema esatto, gesti disattivarlo su questo oggetto prima di rimuoverla:

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

Questo dovrebbe fare il trucco.

[EDIT] Un'altra soluzione che ha funzionato per me: non utilizzare "autorelease" per i riconoscitori di gesti. Nella maggior parte dei casi è possibile rilasciare il riconoscimento direttamente dopo averlo aggiunto a una vista.

+0

Se li si utilizza come IBOutlet, assicurarsi che siano deboli e quindi annullare la proprietà dopo aver terminato di usarlo, se necessario. Come la modifica sopra, ma potrebbe non essere ovvio per alcuni. – cynistersix

0

è qualcosa che non va semplicemente facendo questo:

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

Sembra che la tua riconoscitore gesto sta inviando un callback al controller dopo il controller è stato deallocato. Assicurati di rimuovere il tuo riconoscitore di gesti dalla vista a cui l'hai collegato prima di deallocare il controller.

Nella tua classe controller, probabilmente istituito il vostro gesto riconoscitore qualcosa di simile:

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

Quindi assicuratevi di rimuovere il sistema di riconoscimento gesto metodo dealloc del controller:

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

Ecco un ovvia soluzione di come l'ho risolto .. assicurati di rilasciare la tua vista attuale.Il mio punto di vista aveva una serie di sottoview che stavo rilasciando ma non ho rilasciato la mia visione attuale. Dopo che l'ho fatto, il programma è andato bene.

Problemi correlati