Tengo 2 separados navigationcontrollers
, uno con RootViewController
A y el otro con RootViewController
B.
Puedo presionar ViewController
C en la pila de navegación de A o B.
Pregunta: Cuando estoy en ViewController
C, ¿cómo puedo saber si estoy en la pila que pertenece a A o B?
Respuestas:
Se podría utilizar el
UINavigationController
'sviewControllers
de propiedad:https://developer.apple.com/documentation/uikit/uinavigationcontroller
Puede usar eso para probar si el controlador de vista raíz (el que está en el índice de matriz 0) es el controlador de vista A o B.
fuente
var viewControllers: [UIViewController]
viewControllers.last
viewControllers.last
tiene un controlador de vista actual, para obtener el controlador de vista anterior, se debe usarviewControllers[viewControllers.count-2]
Aquí está la implementación de la respuesta aceptada:
- (UIViewController *)backViewController { NSInteger numberOfViewControllers = self.navigationController.viewControllers.count; if (numberOfViewControllers < 2) return nil; else return [self.navigationController.viewControllers objectAtIndex:numberOfViewControllers - 2]; }
fuente
UIViewController
- (UIViewController *)backViewController { NSInteger myIndex = [self.navigationController.viewControllers indexOfObject:self]; if ( myIndex != 0 && myIndex != NSNotFound ) { return [self.navigationController.viewControllers objectAtIndex:myIndex-1]; } else { return nil; } }
fuente
Una implementación más general de la respuesta aceptada:
- (UIViewController *)backViewController { NSArray * stack = self.navigationController.viewControllers; for (int i=stack.count-1; i > 0; --i) if (stack[i] == self) return stack[i-1]; return nil; }
Esto devolverá el "controlador de vista posterior" correcto independientemente de dónde esté la clase actual en la pila de navegación.
fuente
Implementación rápida del código tjklemz como extensión:
extension UIViewController { func backViewController() -> UIViewController? { if let stack = self.navigationController?.viewControllers { for(var i=stack.count-1;i>0;--i) { if(stack[i] == self) { return stack[i-1] } } } return nil } }
fuente
Aquí hay una versión modificada del código Swift de Prabhu Beeman que lo adapta para admitir Swift 3:
extension UIViewController { func backViewController() -> UIViewController? { if let stack = self.navigationController?.viewControllers { for i in (1..<stack.count).reverse() { if(stack[i] == self) { return stack[i-1] } } } return nil } }
fuente
Acceda al
n-2
elemento de laviewControllers
propiedad para acceder al controlador de vista principal.Una vez que tenga esa instancia, puede verificar su tipo registrando lo que sale de la
NSStringFromClass()
función. O puede mantener algunastatic const
cadena de identificación en los controladores A y B, y una función getter que imprima la cadena.fuente
Como
UINavigationController
extensión:extension UINavigationController { func previousViewController() -> UIViewController? { guard viewControllers.count > 1 else { return nil } return viewControllers[viewControllers.count - 2] } }
fuente
Implementación rápida del código @tjklemz:
var backViewController : UIViewController? { var stack = self.navigationController!.viewControllers as Array for (var i = stack.count-1 ; i > 0; --i) { if (stack[i] as UIViewController == self) { return stack[i-1] as? UIViewController } } return nil }
fuente
println("backViewController is: \(backViewController.description)")
; esto le dará una descripción como "UINavigationController: 0x7fcea1d286b0", que no es muy clara pero al menos le permite identificar el objeto. Como dije, no estoy seguro de lo que necesita exactamente ...Utilice el
navigationController
método para recuperarlo. Consulte la documentación en el sitio de Apple .fuente
Porque a los caballos muertos les gusta ser golpeados :)
- (UIViewController *)previousViewController { NSArray *vcStack = self.navigationController.viewControllers; NSInteger selfIdx = [vcStack indexOfObject:self]; if (vcStack.count < 2 || selfIdx == NSNotFound) { return nil; } return (UIViewController *)[vcStack objectAtIndex:selfIdx - 1]; }
fuente
Una impementación Swift más sucinta:
extension UIViewController { var previousViewController: UIViewController? { guard let nav = self.navigationController, let myIdx = nav.viewControllers.index(of: self) else { return nil } return myIdx == 0 ? nil : nav.viewControllers[myIdx-1] } }
fuente
Encontrar el controlador de vista anterior es simple.
En tu caso, es decir, estás en C y necesitas B,
[self.navigationController.viewControllers lastObject]
es lo que quieres.Para A, dado que A es el controlador de vista raíz, puede simplemente reemplazar
lastObject
confirstObject
para obtener.fuente
Implementación para Swift 2.2: agregue esto en una
UIViewController
extensión. Seguro en el sentido de que volveránil
si el viewcontroller es rootvc o no en un navigationcontroller.var previousViewController: UIViewController? { guard let viewControllers = navigationController?.viewControllers else { return nil } var previous: UIViewController? for vc in viewControllers{ if vc == self { break } previous = vc } return previous }
fuente
Con Swift usando guardia.
extension UIViewController { func getPreviousViewController() -> UIViewController? { guard let _ = self.navigationController else { return nil } guard let viewControllers = self.navigationController?.viewControllers else { return nil } guard viewControllers.count >= 2 else { return nil } return viewControllers[viewControllers.count - 2] } }
fuente
Mi extensión, Swift 3
extension UIViewController { var previousViewController: UIViewController? { guard let controllers = navigationController?.viewControllers, controllers.count > 1 else { return nil } switch controllers.count { case 2: return controllers.first default: return controllers.dropLast(2).first } } }
fuente
para swift 3 puedes hacer esto:
var backtoViewController:UIViewController! for viewController in (self.navigationController?.viewControllers)!.reversed() { if viewController is NameOfMyDestinationViewController { backtoViewController = viewController } } self.navigationController!.popToViewController(backtoViewController, animated: true)
Solo necesita reemplazar "NameOfMyDestinationViewController" por viewController que desea devolver.
fuente