Me he encontrado con un par de casos en los que sería conveniente poder encontrar el controlador de vista "superior" (el responsable de la vista actual), pero no he encontrado la manera de hacerlo.
Básicamente, el desafío es este: dado que uno está ejecutando en una clase que no es un controlador de vista (o una vista) [y no tiene la dirección de una vista activa] y no se le ha pasado la dirección del controlador de vista superior ( o, digamos, la dirección del controlador de navegación), ¿es posible encontrar ese controlador de vista? (Y, si es así, ¿cómo?)
O, en su defecto, ¿es posible encontrar la vista más alta?
ios
objective-c
uiview
uiviewcontroller
uikit
Hot Licks
fuente
fuente
Respuestas:
iOS 4 introdujo la propiedad rootViewController en UIWindow:
Sin embargo, deberá configurarlo usted mismo después de crear el controlador de vista.
fuente
-[UINavigationController topViewController]
). Luego está la palabra "raíz", que es la raíz del árbol (como-[UIWindow rootViewController]
.Creo que necesita una combinación de la respuesta aceptada y @ fishstix
Swift 3.0+
fuente
UINavigationController
y solicitarlotopViewController
o incluso verificarloUITabBarController
y solicitarloselectedViewController
. Esto le dará el controlador de vista que actualmente es visible para el usuario.Para completar la respuesta de JonasG (que omitió los controladores de la barra de pestañas mientras recorría), aquí está mi versión de devolver el controlador de vista actualmente visible:
fuente
childViewControllers
Una versión completa no recursiva, que se ocupa de diferentes escenarios:
UINavigationController
UITabBarController
C objetivo
Swift 4+
fuente
visibleViewController
para dejar en claro lo que hace.Obteniendo el mejor controlador de vista para Swift usando extensiones
Código:
Uso:
fuente
Para completar la respuesta de Eric (que omitió popovers, controladores de navegación, controladores de barra de pestañas, controladores de vista agregados como subvistas a otros controladores de vista durante el desplazamiento), aquí está mi versión de devolver el controlador de vista actualmente visible:
================================================== ===================
================================================== ===================
Y ahora todo lo que necesita hacer para obtener el mejor controlador de vista es llamar al método anterior de la siguiente manera:
fuente
Esta respuesta incluye
childViewControllers
y mantiene una implementación limpia y legible.fuente
Hace poco recibí esta situación en uno de mis proyectos, que requería mostrar una vista de notificación, independientemente del controlador que se mostrara y del tipo (UINavigationController, controlador clásico o controlador de vista personalizado), cuando el estado de la red cambió.
Así que simplemente publiqué mi código, que es bastante fácil y en realidad se basa en un protocolo para que sea flexible con cada tipo de controlador de contenedor. Parece estar relacionado con las últimas respuestas, pero de una manera muy flexible.
Puedes obtener el código aquí: PPTopMostController
Y obtuve el mejor controlador usando
fuente
Esta es una mejora a la respuesta de Eric:
_topMostController(UIViewController *cont)
Es una función auxiliar.¡Ahora todo lo que necesita hacer es llamar
topMostController()
y se debe devolver la mayor cantidad de UIViewController!fuente
self
debería pertenecer.Aquí está mi opinión sobre esto. Gracias a @Stakenborg por señalar la forma de omitir obtener UIAlertView como el controlador más superior
fuente
getSomething:
en Objective-C. Esto tiene un significado especial (más: cocoadevcentral.com/articles/000082.php ) y no cumple con estos requisitos en su código.fuente
fuente
Para la última versión de Swift:
cree un archivo, asígnele un nombre
UIWindowExtension.swift
y pegue el siguiente fragmento:Úselo en cualquier lugar como:
fuente
switch
lugar de si más. 3. No estoy seguro de que necesite una función estática también, creo que podría hacerlo fácilmente en el nivel de primera instancia var que declaró. 4. Probablemente sea mejor no crear demasiadas funciones globales, pero eso es cuestión de gustos. Puede usar una línea de código para lograr el efecto de la función global:UIApplication.sharedApplication().delegate?.window?.visibleViewController
Extensión simple para
UIApplication
en Swift:NOTA:
Se preocupa por
moreNavigationController
dentroUITabBarController
Uso simple:
fuente
Use la extensión a continuación para tomar la corriente visible
UIViewController
. Trabajó para Swift 4.0 y posteriorSwift 4.0 y posterior:
¿Cómo utilizar?
fuente
presentedViewController
primero, antes de los casosUINavigationController
yUITabBarController
? De lo contrario, si un controlador de vista se presenta modalmente desde unUINavigationController
oUITabBarController
, no se devolverá como el controlador de vista superior, aunque sea el controlador de vista el que esté visible.Sin embargo, otra solución rápida
fuente
Extensión Swift 4.2
Úselo desde cualquier lugar como,
o como
Se ajusta a cualquier clase como UINavigationController, UITabBarController
¡Disfrutar!
fuente
Esto es lo que funcionó para mí.
Descubrí que a veces el controlador era nulo en la ventana clave, ya que keyWindow es algo del sistema operativo como una alerta, etc.
fuente
Ampliando la respuesta de @ Eric, debe tener cuidado de que keyWindow sea en realidad la ventana que desea. Si está intentando utilizar este método después de tocar algo en una vista de alerta, por ejemplo, keyWindow será en realidad la ventana de alerta, y eso sin duda le causará problemas. Esto me sucedió en la naturaleza cuando manejaba enlaces profundos a través de una alerta y causaba SIGABRT sin RASTREO DE APILAMIENTO. Perra total para depurar.
Aquí está el código que estoy usando ahora:
Siéntase libre de mezclar esto con cualquier sabor de recuperar el controlador de vista superior que desee de las otras respuestas a esta pregunta.
fuente
Solución alternativa rápida:
fuente
Esta solución es la más completa. Toma en consideración: UINavigationController UIPageViewController UITabBarController Y el controlador de vista más arriba presentado desde el controlador de vista superior
El ejemplo está en Swift 3.
Hay 3 sobrecargas
fuente
Una solución concisa pero completa en Swift 4.2, tiene en cuenta los controles UINavigationControllers , UITabBarControllers , presentados y los controladores de vista secundarios :
Uso:
fuente
Gran solución en Swift, implementar en AppDelegate
fuente
Creo que la mayoría de las respuestas se han ignorado por completo
UINavigationViewController
, por lo que manejé este caso de uso con la siguiente implementación.fuente
Sé que es muy tarde y podría ser redundante. Pero el siguiente es el fragmento que se me ocurrió y que funciona para mí:
fuente
Esto funciona muy bien para encontrar el controlador de vista superior 1 desde cualquier control de vista raíz
fuente
No estoy seguro de si esto ayudará a lo que está tratando de lograr al encontrar el controlador de vista superior, pero estaba tratando de presentar un nuevo controlador de vista, pero si mi controlador de vista raíz ya tenía un diálogo modal, estaría bloqueado, por lo que iría a la parte superior de todos los controladores de vista modal usando este código:
fuente
puedes encontrar el controlador de vista más alto usando
fuente
self
no tiene ningunanavigationController
propiedad.Otra solución se basa en la cadena de respuesta, que puede o no funcionar dependiendo de cuál sea la primera respuesta:
Pseudocódigo de ejemplo:
fuente
Rápido:
Uso:
fuente