2011-05-11 21 views
30

Tengo una vista que es UIViewController (raíz) que maneja los anuncios y UINavigationController. En ese UINavigationController tengo capas típicas de controladores. En mi controlador de vista de tabla de configuraciones personalizadas, tengo un botón para contactarme para soporte. Cuando el usuario hace clic en este botón, creo un MFMailComposeViewController y me gustaría presentarlo. No puedo presentarlo desde la vista de tabla de configuración, ya que estará debajo de mis anuncios, por lo que necesito hacer referencia a la vista raíz y presentarla desde allí. He intentado self.parentViewController.parentViewController donde self es la vista de tabla de configuraciones, pero eso no funciona. ¿Cómo debería hacer referencia a esto? Parece un mal diseño tener que hacer referencia directamente a la vista raíz y pasarla a la vista de configuración.Cómo encontrar Root UIViewController

+0

¿Ha intentado self.navigationController? No estoy seguro de cómo está configurada su jerarquía de vistas. – jaminguy

Respuesta

78

Obtener el keyWindow actual:

UIWindow *window = [UIApplication sharedApplication].keyWindow; 

Obtener su RootViewController:

UIViewController *rootViewController = window.rootViewController; 

NOTA: Si actualmente se muestra un UIAlertView, un nuevo viento ow se está creando y asignando para ser la ventana clave. También puede haber otros casos excepcionales que no mantengan la ventana de la aplicación como la ventana clave.

+1

Esto solo funciona en 4.0+ por cierto. UIWindow no tenía una propiedad rootViewController anterior a 4.0. –

+1

@Jesse buen punto - Estoy tan contento de no tener que soportar esos ladrillos antiguos nunca más;). – Till

+0

sí, apesta. Yo diría que es al menos el 50% de mi tiempo. –

2

Utilice la aplicación singleton. Algo así como:

[[[UIApplication sharedApplication] delegate] rootViewController] debe conseguirlo si su viewController que es la raíz se llama rootViewController

-4

Obtiene el objeto UIApplication. Haz un ciclo por la matriz de ventanas para encontrar la ventana clave. Y luego obtenga la propiedad rootViewController.

31

En mi experiencia, esta es la solución ideal para obtener el rootViewController:

[[[[UIApplication sharedApplication] delegate] window] rootViewController]

Nota: En caso de un activo UIAlert o UIActionSheet, se obtiene la Hoja de alerta o acción como su ventana de clave .

+0

+1 Esta es la única manera segura y confiable de hacerlo. Tomó años para que rastreara un error de alerta + keyWindow, ¡y esta publicación me salvó! – stonemonk

+2

¡Segundo eso! El enfoque keyWindow (actualmente marcado como la respuesta correcta) no es confiable, ya que la ventana clave puede cambiar. –

+0

también tenía un error al usar KeyWindow durante un UIAlertView ... ¡gracias por esto! este es el mejor método para usar. – manroe

1

Siempre se puede resolver esto con 1 línea de código pero recomiendo esta manera Swift hacerlo, puede llamar a esto desde cualquier lugar, su también de choque y fallo de seguridad:

/// EZSwiftExtensions - Gives you the VC on top so you can easily push your popups 
var topMostVC: UIViewController? { 
    var presentedVC = UIApplication.sharedApplication().keyWindow?.rootViewController 
    while let pVC = presentedVC?.presentedViewController { 
     presentedVC = pVC 
    } 

    if presentedVC == nil { 
     print("EZSwiftExtensions Error: You don't have any views set. You may be calling them in viewDidLoad. Try viewDidAppear instead.") 
    } 
    return presentedVC 
} 

Su incluido como estándar en función de:

https://github.com/goktugyil/EZSwiftExtensions