que containerview container change swift uiviewcontroller

swift - containerview - Obtenga la mayoría de UIViewController



view controller que es (17)

Parece que no puedo obtener la mayor cantidad de UIViewController sin acceso a un UINavigationController . Esto es lo que tengo hasta ahora:

UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(vc, animated: true, completion: nil)

Sin embargo, no parece hacer nada. keyWindow y rootViewController parecen ser valores no nulos, por lo que el encadenamiento opcional no debería ser un problema.

NOTA: es una mala idea hacer algo como esto. Rompe el patrón MVC.


¿Dónde pusiste el código?

Probé tu código en mi demo, descubrí, si pones el código en

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

fallará, porque la ventana clave se ha configurado todavía.

Pero puse tu código en algún controlador de vista

override func viewDidLoad() {

Simplemente funciona


Basado en Bob -c arriba:

Swift 3.0

extension UIWindow { func visibleViewController() -> UIViewController? { if let rootViewController: UIViewController = self.rootViewController { return UIWindow.getVisibleViewControllerFrom(vc: rootViewController) } return nil } class func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController { if vc.isKind(of: UINavigationController.self) { let navigationController = vc as! UINavigationController return UIWindow.getVisibleViewControllerFrom( vc: navigationController.visibleViewController!) } else if vc.isKind(of: UITabBarController.self) { let tabBarController = vc as! UITabBarController return UIWindow.getVisibleViewControllerFrom(vc: tabBarController.selectedViewController!) } else { if let presentedViewController = vc.presentedViewController { return UIWindow.getVisibleViewControllerFrom(vc: presentedViewController) } else { return vc; } } } }


Basado en la respuesta de Dianz, la versión Objective-C

- (UIViewController *) topViewController { UIViewController *baseVC = UIApplication.sharedApplication.keyWindow.rootViewController; if ([baseVC isKindOfClass:[UINavigationController class]]) { return ((UINavigationController *)baseVC).visibleViewController; } if ([baseVC isKindOfClass:[UITabBarController class]]) { UIViewController *selectedTVC = ((UITabBarController*)baseVC).selectedViewController; if (selectedTVC) { return selectedTVC; } } if (baseVC.presentedViewController) { return baseVC.presentedViewController; } return baseVC; }


Demasiados sabores pero ninguno uno elaborado e iterativo. Combinado de los anteriores:

func topMostController() -> UIViewController? { var from = UIApplication.shared.keyWindow?.rootViewController while (from != nil) { if let to = (from as? UITabBarController)?.selectedViewController { from = to } else if let to = (from as? UINavigationController)?.visibleViewController { from = to } else if let to = from?.presentedViewController { from = to } else { break } } return from }


En un caso muy raro, con segue personalizado, el controlador de vista superior no está en una pila de navegación o controlador de barra de pestañas o presentado, pero su vista se inserta en la parte superior de las subvistas de ventanas clave.

En tal situación, es necesario verificar si UIApplication.shared.keyWindow.subviews.last == self.view para determinar si el controlador de vista actual es el más alto.


La mejor solución para mí es una extensión con una función. Crea un archivo rápido con esta extensión

Primero es la extensión UIWindow :

public extension UIWindow { var visibleViewController: UIViewController? { return UIWindow.visibleVC(vc: self.rootViewController) } static func visibleVC(vc: UIViewController?) -> UIViewController? { if let navigationViewController = vc as? UINavigationController { return UIWindow.visibleVC(vc: navigationViewController.visibleViewController) } else if let tabBarVC = vc as? UITabBarController { return UIWindow.visibleVC(vc: tabBarVC.selectedViewController) } else { if let presentedVC = vc?.presentedViewController { return UIWindow.visibleVC(vc: presentedVC) } else { return vc } } } }

dentro de esa función de agregar archivo

func visibleViewController() -> UIViewController? { let appDelegate = UIApplication.shared.delegate if let window = appDelegate!.window { return window?.visibleViewController } return nil }

Y si desea usarlo, puede llamarlo en cualquier lugar. Ejemplo :

override func viewDidLoad() { super.viewDidLoad() if let topVC = visibleViewController() { //show some label or text field } }

El código del archivo es así :

import UIKit public extension UIWindow { var visibleViewController: UIViewController? { return UIWindow.visibleVC(vc: self.rootViewController) } static func visibleVC(vc: UIViewController?) -> UIViewController? { if let navigationViewController = vc as? UINavigationController { return UIWindow.visibleVC(vc: navigationViewController.visibleViewController) } else if let tabBarVC = vc as? UITabBarController { return UIWindow.visibleVC(vc: tabBarVC.selectedViewController) } else { if let presentedVC = vc?.presentedViewController { return UIWindow.visibleVC(vc: presentedVC) } else { return vc } } } } func visibleViewController() -> UIViewController? { let appDelegate = UIApplication.shared.delegate if let window = appDelegate!.window { return window?.visibleViewController } return nil }


Me encantó la respuesta de @ dianz , así que aquí está la versión rápida de 3. Básicamente es lo mismo, pero le faltaba una llave y algunos de los nombres de sintaxis / variable / método han cambiado. ¡Asi que aqui esta!

extension UIApplication { class func topViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? { if let nav = base as? UINavigationController { return topViewController(base: nav.visibleViewController) } if let tab = base as? UITabBarController { if let selected = tab.selectedViewController { return topViewController(base: selected) } } if let presented = base?.presentedViewController { return topViewController(base: presented) } return base } }

Sin embargo, el uso sigue siendo exactamente el mismo:

if let topController = UIApplication.topViewController() { print("The view controller you''re looking at is: /(topController)") }


Para encontrar la vista visible Controlador en Swift 3

if let viewControllers = window?.rootViewController?.childViewControllers { let prefs = UserDefaults.standard if viewControllers[viewControllers.count - 1] is ABCController{ print("[ABCController] is visible") } }

Este código encuentra visible el último controlador agregado o el último controlador activo.

Esto lo he usado en AppDelegate para encontrar el controlador de vista activo


Use este código para encontrar los mejores UIViewController

func getTopViewController() -> UIViewController? { var topController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController while topController?.presentedViewController != nil { topController = topController?.presentedViewController } return topController }


Variación leve en @AlberZou usando una variable calculada en lugar de una función

extension UIViewController { var topMostViewController : UIViewController { if let presented = self.presentedViewController { return presented.topMostViewController } if let navigation = self as? UINavigationController { return navigation.visibleViewController?.topMostViewController ?? navigation } if let tab = self as? UITabBarController { return tab.selectedViewController?.topMostViewController ?? tab } return self } } extension UIApplication { var topMostViewController : UIViewController? { return self.keyWindow?.rootViewController?.topMostViewController } }

Luego dice

if let topViewControler = UIApplication.shared.topMostViewController { ... do stuff }


puede definir una variable UIViewController en AppDelegate y, en cada vista, WillAppear establecer la variable en self (sin embargo, dianz answer es la mejor respuesta).

override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) let appDel = UIApplication.sharedApplication().delegate as! AppDelegate appDel.currentVC = self }


tener esta extensión

Swift 2. *

extension UIApplication { class func topViewController(controller: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? { if let navigationController = controller as? UINavigationController { return topViewController(navigationController.visibleViewController) } if let tabController = controller as? UITabBarController { if let selected = tabController.selectedViewController { return topViewController(selected) } } if let presented = controller?.presentedViewController { return topViewController(presented) } return controller } }

Swift 3

extension UIApplication { class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? { if let navigationController = controller as? UINavigationController { return topViewController(controller: navigationController.visibleViewController) } if let tabController = controller as? UITabBarController { if let selected = tabController.selectedViewController { return topViewController(controller: selected) } } if let presented = controller?.presentedViewController { return topViewController(controller: presented) } return controller } }

Puedes usar esto en cualquier lugar de tu controlador

if let topController = UIApplication.topViewController() { }


https://gist.github.com/db0company/369bfa43cb84b145dfd8 Hice algunas pruebas sobre las respuestas y comentarios en este sitio. Para mí, los siguientes trabajos

extension UIViewController { func topMostViewController() -> UIViewController { if let presented = self.presentedViewController { return presented.topMostViewController() } if let navigation = self as? UINavigationController { return navigation.visibleViewController?.topMostViewController() ?? navigation } if let tab = self as? UITabBarController { return tab.selectedViewController?.topMostViewController() ?? tab } return self } } extension UIApplication { func topMostViewController() -> UIViewController? { return self.keyWindow?.rootViewController?.topMostViewController() } }

Luego, obtenga la vista superior Controlador por:

UIApplication.shared.topMostViewController()


presentViewController muestra un controlador de vista. No devuelve un controlador de vista. Si no está utilizando un UINavigationController , probablemente esté buscando presentedViewController y deberá comenzar en la raíz e iterar hacia abajo a través de las vistas presentadas.

if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController { while let presentedViewController = topController.presentedViewController { topController = presentedViewController } // topController should now be your topmost view controller }

Para Swift 3+:

if var topController = UIApplication.shared.keyWindow?.rootViewController { while let presentedViewController = topController.presentedViewController { topController = presentedViewController } // topController should now be your topmost view controller }


Para un rápido 4/5 + para obtener la vista más alta

// MARK: UIApplication extensions extension UIApplication { class func getTopViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? { if let nav = base as? UINavigationController { return getTopViewController(base: nav.visibleViewController) } else if let tab = base as? UITabBarController, let selected = tab.selectedViewController { return getTopViewController(base: selected) } else if let presented = base?.presentedViewController { return getTopViewController(base: presented) } return base } }

Cómo utilizar

if let topVC = UIApplication.getTopViewController() { topVC.view.addSubview(forgotPwdView) }


extension UIWindow { func visibleViewController() -> UIViewController? { if let rootViewController: UIViewController = self.rootViewController { return UIWindow.getVisibleViewControllerFrom(vc: rootViewController) } return nil } static func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController { if let navigationController = vc as? UINavigationController, let visibleController = navigationController.visibleViewController { return UIWindow.getVisibleViewControllerFrom( vc: visibleController ) } else if let tabBarController = vc as? UITabBarController, let selectedTabController = tabBarController.selectedViewController { return UIWindow.getVisibleViewControllerFrom(vc: selectedTabController ) } else { if let presentedViewController = vc.presentedViewController { return UIWindow.getVisibleViewControllerFrom(vc: presentedViewController) } else { return vc } } } }

Uso:

if let topController = window.visibleViewController() { println(topController) }


var topViewController: UIViewController? { guard var topViewController = UIApplication.shared.keyWindow?.rootViewController else { return nil } while let presentedViewController = topViewController.presentedViewController { topViewController = presentedViewController } return topViewController }