2013-12-17 5 views
16

Esiste una soluzione pulita per ottenere un callback o un evento sul controller di visualizzazione che viene rimosso (spuntato) da un interactivePopGestureRecognizer?Getting interactivePopGestureRecognizer respinge callback/evento

Per essere chiari, ho bisogno di un metodo esplicito per richiamare il controller più in alto (e nessun altro) prima che il controller venga scoccato da questo riconoscitore di gesti. Non voglio ottenere l'evento sul controller di navigazione e inviare l'evento al controller appropriato e non voglio usare viewWillAppear o viewWillDissapear ...

La cosa più vicina che ho è aggiungere una coppia target/selector a il gesto ha solo 2 problemi. Per prima cosa non riesco a ottenere informazioni dirette se il controller verrà rimosso o meno (UIGestureRecognizerStateEnded verrà attivato in ogni caso). Secondo dopo che il controller è stato rimosso, devo rimuovere il target dal riconoscitore.

Il motivo è che ho alcuni controller che devono inviare alcune informazioni ai propri delegati. Con i pulsanti "done" e "cancel" l'evento viene attivato, i metodi delegate vengono richiamati e quindi il controller viene spuntato. Ho più o meno bisogno che succeda con il minor numero possibile di modifiche al codice.

Un'altra situazione su questo gesto è la possibilità di lanciare una vista di avviso e di ripristinare l'azione: C'è un modo di mostrare la vista di avviso quando questo gesto finisce chiedendo come "sei sicuro di voler cancellare il tuo lavoro" e avere l'utente scegliere se il controller verrà scoppiato o riportato.

+0

Problema interessante. Ho la sensazione che è necessario disabilitare il 'interactivePopGestureRecognizer' e registrarne uno o utilizzare le [transizioni interattive] di iOS 7 (http://www.objc.io/issue-5/view-controller-transitions.html) –

+0

Temo che potresti avere ragione. Sembra strano questo non è un problema comune. Mi aspetterei che alcune app necessitino di implementarlo almeno ad un certo punto.La cosa peggiore di implementare una transizione personalizzata è che devi disabilitare in modo esplicito il gesto su ciascuno di questi controller e riattivarlo dopo che è stato scoppiato (o è stato premuto un altro). –

risposta

38

So che questo è vecchio ma per chiunque abbia problemi simili. Ecco l'approccio che ho usato. Innanzitutto registro un UINavigationControllerDelegate al mio controller di navigazione. Il delegato deve implementare.

Objective-C

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated

Swift

func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) 

Così l'implementazione sarebbe simile a questa.

Objective-C

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated 
{ 
     id<UIViewControllerTransitionCoordinator> tc = navigationController.topViewController.transitionCoordinator; 
     [tc notifyWhenInteractionEndsUsingBlock:^(id<UIViewControllerTransitionCoordinatorContext> context) { 
      NSLog(@"Is cancelled: %i", [context isCancelled]); 
    }]; 
} 

Swift

func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) { 
    if let coordinator = navigationController.topViewController?.transitionCoordinator() { 
     coordinator.notifyWhenInteractionEndsUsingBlock({ (context) in 
      print("Is cancelled: \(context.isCancelled())") 
     }) 
    } 
} 

La richiamata scatterà quando l'utente solleva il dito e il (Objec-C) [context isCancelled]; (Swift) context.isCancelled() tornerà YES/true se l'animazione è stata invertita (il controller della vista non è stato spuntato), altrimenti NO/false. Ci sono più cose nello che possono essere utili, come entrambi i controller di visualizzazione coinvolti e la percentuale dell'animazione che è stata completata al rilascio ecc.

+1

Non è adatto per "Non voglio ottenere l'evento sul controller di navigazione e inviare l'evento al controller appropriato" ma è comunque abbastanza buono. –

+1

Sì, lo so che non è perfetto per te, ma la tua domanda è una delle prime se provi a cercare su Google questo tipo di problema in modo che possa funzionare per alcuni. E tecnicamente non lo ottieni sul controller di navigazione ma sul delegato, ma sì, devi comunque chiamare un metodo sul controller. Se si desidera provare, è possibile utilizzare isCancelled per verificare se si desidera notificare o meno e quindi utilizzare [context viewControllerForKey: UITransitionContextFromViewControllerKey] per ottenere la notifica da parte del controller. Ma di nuovo hai ragione, non è quello per cui sei stato promosso. –

+1

In realtà avendo il più alto di controllo posso realizzare qualcosa di simile: if ([tc respondsToSelector: @selector (controllerDismissedByPopGesture :)]) { [tc performSelector: @selector (controllerDismissedByPopGesture :) withObject: @ ([contesto isCancelled ])]; } Anche se non mi piace molto questo tipo di codice, fa esattamente quello di cui ho bisogno. Tutto ciò di cui ho bisogno è aggiungere il '- (void) controllerDismissedByPopGesture: (NSNumber *) isCancelled' a QUALSIASI controller e ho finito. Forse dovresti aggiungerlo alla risposta ... –