È possibile utilizzare setViewControllers(_:animated:)
per riorganizzare lo stack View Controller. Non devi fare nulla di speciale per far funzionare correttamente il pulsante Indietro. Il controller di navigazione imposta il pulsante Indietro in base al secondo elemento nell'array viewControllers
(se esiste un secondo elemento) e aggiorna il pulsante Indietro ogni volta che aggiorna l'array viewControllers
.
Ecco come farei questo. Innanzitutto, aggiungiamo un metodo a UIViewController
per chiedere se è il controller di visualizzazione per uno specifico userId
. Poiché la maggior parte controller di vista non sono (e non possono essere) il controller della vista corretta, semplicemente ritorna false
:
extension UIViewController {
func isViewControllerForUserId(userId: Int) -> Bool {
return false
}
}
Poi abbiamo ignorare questo metodo in MessagesViewController
per tornare true
se del caso:
extension MessagesViewController {
override func isViewControllerForUserId(userId: Int) -> Bool {
return self.userId == userId
}
}
Ora, per mostrare il controller di visualizzazione per un utente specifico, cerchiamo lo stack del controller di navigazione per un controller di visualizzazione esistente. La nostra azione dipende dal fatto che lo troviamo:
func showMessageForUserId(userId: Int) {
if let index = navController.viewControllers.indexOf({ $0.isViewControllerForUserId(userId) }) {
navController.moveToTopOfNavigationStack(viewControllerAtIndex: index)
} else {
pushNewViewControllerForUserId(userId)
}
}
Se non l'abbiamo trovato, facciamo un nuovo controller della vista e spingerlo:
private func pushNewViewControllerForUserId(userId: Int) {
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
vc.userId = userId
self.navController.pushViewController(vc, animated: true)
}
Se l'abbiamo trovato, abbiamo spostarlo in cima alla pila di navigazione con questo metodo:
extension UINavigationController {
func moveToTopOfNavigationStack(viewControllerAtIndex index: Int) {
var stack = viewControllers
if index == stack.count - 1 {
// nothing to do because it's already on top
return
}
let vc = stack.removeAtIndex(index)
if (reorderingIsBuggy) {
setViewControllers(stack, animated: false)
}
stack.append(vc)
setViewControllers(stack, animated: true)
}
private var reorderingIsBuggy: Bool {
// As of iOS 9.3 beta 3, `UINavigationController` drops the prior top-of-stack
// when you use `setViewControllers(_:animated:)` to move a lower item to the
// top with animation. The workaround is to remove the lower item from the stack
// without animation, then add it to the top of the stack with animation. This
// makes it display a push animation instead of a pop animation and avoids
// dropping the prior top-of-stack.
return true
}
}
Grazie Rob. Ho stampato la pila dopo averla rimossa all'indice e aggiunta. È stampato nell'ordine corretto, quindi sembra a posto.Quando chiamo '' 'setViewControllers''', tutto sembra a posto e il VC desiderato viene mostrato in alto. Tuttavia, il VC prima di ottenere '' 'deinit''' e scompare. Sai perché il precedente VC scompare? (Sto solo testando su 2 VC) – TIMEX
Nota: Ho modificato questa riga: '' 'navController.setViewControllers (stack, animato: false)' '' per l'animazione: false, e tutto sembra funzionare correttamente. Qualche idea sul perché questo cambiamento ha risolto il problema? – TIMEX
Quale controller di visualizzazione esegue 'deinit'? –