2014-09-09 13 views
28

Sto scrivendo un'app solo iOS 8 e sto utilizzando le nuove presentazioni adattive utilizzando una combinazione di "Mostra" e "Mostra dettagli" e showViewController:sender: e showDetailViewController:sender: metodi.Che cosa è l'opposto programmatico di showViewController: mittente:

La mia domanda è qual è il modo programmatico di tornare dopo aver chiamato showViewController:sender:? Il modo in cui viene mostrato il controller della vista dipende dal suo contesto genitore. Per esempio. in un UINavigationControllershowViewController:sender: inserisce un nuovo controller nello stack di navigazione ma se non c'è un contenitore UIKit nel grafico del controller di visualizzazione, showViewController:sender: termina invece facendo una presentazione.

Considerando ho potuto scrivere il mio regolatore contenitore arbitrario sembra impraticabile controllare

if (self.navigationController) { 
    [self.navigationController popViewControllerAnimated:YES]; 
} 
else if (self.presentingViewController){ 
... 
else if ([self.parentViewController isKindOfClass:[CrazyCustomContainer class]]){ 
    [self.parentViewController someWackyUnwindMethod]; 
} 
... 

ecc ... quindi c'è un modo generico per invertire viene mostrato? Se no, l'unica soluzione che vedo è quella di usare i segui di unwind per tutto. Non troppo di una seccatura ma sono curioso.

+1

Penso che una parte di questo è perché con un modello avresti un pulsante di annullamento e chiamerei il normale 'dismissViewControllerAnimated:' e con un controller di navigazione avrebbe un pulsante indietro incorporato. Quindi non devi spesso gestire i licenziamenti nello stesso modo in cui gestisci le presentazioni. –

+1

Ma questo è il mio punto: 'showViewController:' può fare una push o una presentazione. Il controller di visualizzazione presentato non dovrebbe sapere come è stato visualizzato sullo schermo, quindi fare qualcosa come '[self.navigationController popViewControllerAnimated:]' nel presentato non è buono se a volte può fallire perché sei stato presentato ... – jackslash

+0

Bene per un navController che non avresti bisogno di pop. Avrebbe una schiena. –

risposta

20

C'è un capitolo su come showViewController:sender: e showDetailViewController:sender: funzionano in Programming iOS 8: Dive Deep into Views, View Controllers, and Frameworks.

Quando vengono chiamati questi metodi, chiamano targetViewControllerForAction:sender: e chiamano questo metodo sull'oggetto restituito. L'oggetto target può quindi visualizzare il controller della vista in modo appropriato. Ad esempio, un controller di navigazione spinge il controller di visualizzazione sul suo stack di navigazione.

Quindi è possibile creare un metodo generico dismissVC: e sovrascriverlo in diverse sottoclassi UIViewController.

extension UIViewController { 
    func dismissVC(sender:AnyObject?) { 
     if let presentingVC = targetViewControllerForAction("dismissVC", withSender: sender) as? UIViewController { 
      presentingVC.dismissVC(self) 
     } 
    } 
} 

extension UINavigationController { 
    override func dismissVC(sender: AnyObject?) { 
     popViewControllerAnimated(true) 
    } 
} 

extension CrazyCustomContainer { 
    override func dismissVC(sender: AnyObject?) { 
     someWackyUnwindMethod() 
    } 
} 

In questo modo, quando si chiama dismissVC: metodo, se sarà sempre respingere correttamente il controller della vista a seconda del contesto.

+0

Sì questa è la risposta. Molto bene. – jackslash

+8

Quindi, in base a ciò, la risposta effettiva alla domanda "C'è un opposto programmatico a' showViewController: mittente: '?" è no**. È necessario implementare in modo efficace la propria versione generica utilizzando lo stesso meccanismo sottostante utilizzato da Apple per la presentazione adattiva. – smileyborg

+0

Sì, questo è il caso. Anche se nella domanda sto cercando un'alternativa programmatica per scaricare segues, che ha anche bisogno di codice per supportarli. Questa risposta al 100% soddisfa ciò che volevo. – jackslash

0

Ecco un trucco che ho utilizzato prima dell'esistenza di showViewController che potrebbe essere di aiuto.

if let nav = navigationController { 
    // We have a navigation controller so we'll have a back button 
} 
else { 
    // no navigation controller, need a cancel button 
    // ... Add Cancel Button 
} 

In pratica si controlla dove sei. Successivamente, puoi inserire qualsiasi codice di salvataggio in viewDidDisappear o qualcosa del genere perché funzioni per entrambi. Un'altra opzione è controllare presentationViewController ma ciò non garantisce sempre la presentazione modale.