ios - centro - iPhone-Cómo encontrar el controlador de vista superior
itunes (30)
Ampliando la respuesta de @ Eric, debes tener cuidado de que KeyWindow sea la ventana que deseas. Si está tratando de utilizar este método después de tocar algo en una vista de alerta, por ejemplo, la ventana clave será la ventana de la alerta, y eso sin duda le causará problemas. Esto me sucedió en la naturaleza al manejar enlaces profundos a través de una alerta y causó SIGABRTS SIN RASTREO DE PILAS. Perra total para depurar.
Aquí está el código que estoy usando ahora:
- (UIViewController *)getTopMostViewController {
UIWindow *topWindow = [UIApplication sharedApplication].keyWindow;
if (topWindow.windowLevel != UIWindowLevelNormal) {
NSArray *windows = [UIApplication sharedApplication].windows;
for(topWindow in windows)
{
if (topWindow.windowLevel == UIWindowLevelNormal)
break;
}
}
UIViewController *topViewController = topWindow.rootViewController;
while (topViewController.presentedViewController) {
topViewController = topViewController.presentedViewController;
}
return topViewController;
}
Siéntase libre de mezclar esto con cualquier sabor de recuperación del controlador de vista superior que desee de las otras respuestas en esta pregunta.
Ahora 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 una manera de hacerlo.
Básicamente, el desafío es este: dado que uno se 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 superior?
Aquí está mi opinión sobre esto. Gracias a @Stakenborg por señalar la forma de omitir que UIAlertView sea el mejor controlador
-(UIWindow *) returnWindowWithWindowLevelNormal
{
NSArray *windows = [UIApplication sharedApplication].windows;
for(UIWindow *topWindow in windows)
{
if (topWindow.windowLevel == UIWindowLevelNormal)
return topWindow;
}
return [UIApplication sharedApplication].keyWindow;
}
-(UIViewController *) getTopMostController
{
UIWindow *topWindow = [UIApplication sharedApplication].keyWindow;
if (topWindow.windowLevel != UIWindowLevelNormal)
{
topWindow = [self returnWindowWithWindowLevelNormal];
}
UIViewController *topController = topWindow.rootViewController;
if(topController == nil)
{
topWindow = [UIApplication sharedApplication].delegate.window;
if (topWindow.windowLevel != UIWindowLevelNormal)
{
topWindow = [self returnWindowWithWindowLevelNormal];
}
topController = topWindow.rootViewController;
}
while(topController.presentedViewController)
{
topController = topController.presentedViewController;
}
if([topController isKindOfClass:[UINavigationController class]])
{
UINavigationController *nav = (UINavigationController*)topController;
topController = [nav.viewControllers lastObject];
while(topController.presentedViewController)
{
topController = topController.presentedViewController;
}
}
return topController;
}
Creo que la mayoría de las respuestas han ignorado por completo a UINavigationViewController
, así que UINavigationViewController
este caso de uso con la siguiente implementación.
+ (UIViewController *)topMostController {
UIViewController * topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController || [topController isMemberOfClass:[UINavigationController class]]) {
if([topController isMemberOfClass:[UINavigationController class]]) {
topController = [topController childViewControllers].lastObject;
} else {
topController = topController.presentedViewController;
}
}
return topController;
}
Creo que necesitas una combinación de la respuesta aceptada y @ fishstix''s
+ (UIViewController*) topMostController
{
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
return topController;
}
Swift 3.0+
let rootViewController = UIApplication.shared.keyWindow?.rootViewController
Debajo de dos funciones puede ayudar a encontrar el controlador de vista superior en la pila de controladores de vista. Es posible que necesite personalización más adelante, pero para este código es impresionante entender el concepto de topViewController o pila de viewControllers.
- (UIViewController*)findTopViewController {
id topControler = [self topMostController];
UIViewController* topViewController;
if([topControler isKindOfClass:[UINavigationController class]]) {
topViewController = [[(UINavigationController*)topControler viewControllers] lastObject];
} else if ([topControler isKindOfClass:[UITabBarController class]]) {
//Here you can get reference of top viewcontroller from stack of viewcontrollers on UITabBarController
} else {
//topController is a preented viewController
topViewController = (UIViewController*)topControler;
}
//NSLog(@"Top ViewController is: %@",NSStringFromClass([topController class]));
return topViewController;
}
- (UIViewController*)topMostController
{
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
//NSLog(@"Top View is: %@",NSStringFromClass([topController class]));
return topController;
}
Puede usar el método [viewController Class] para averiguar el tipo de clase de un viewController.
Esta es una mejora de la respuesta de Eric:
UIViewController *_topMostController(UIViewController *cont) {
UIViewController *topController = cont;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
if ([topController isKindOfClass:[UINavigationController class]]) {
UIViewController *visible = ((UINavigationController *)topController).visibleViewController;
if (visible) {
topController = visible;
}
}
return (topController != cont ? topController : nil);
}
UIViewController *topMostController() {
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
UIViewController *next = nil;
while ((next = _topMostController(topController)) != nil) {
topController = next;
}
return topController;
}
_topMostController(UIViewController *cont)
es una función auxiliar.
¡Ahora todo lo que necesita hacer es llamar a topMostController()
y se debe devolver la parte superior de UIViewController!
Esta respuesta incluye childViewControllers
y mantiene una implementación limpia y legible.
+ (UIViewController *)topViewController
{
UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
return [rootViewController topVisibleViewController];
}
- (UIViewController *)topVisibleViewController
{
if ([self isKindOfClass:[UITabBarController class]])
{
UITabBarController *tabBarController = (UITabBarController *)self;
return [tabBarController.selectedViewController topVisibleViewController];
}
else if ([self isKindOfClass:[UINavigationController class]])
{
UINavigationController *navigationController = (UINavigationController *)self;
return [navigationController.visibleViewController topVisibleViewController];
}
else if (self.presentedViewController)
{
return [self.presentedViewController topVisibleViewController];
}
else if (self.childViewControllers.count > 0)
{
return [self.childViewControllers.lastObject topVisibleViewController];
}
return self;
}
Esta solución es la más completa. Se toma en consideración: UINavigationController UIPageViewController UITabBarController y el controlador de vista superior presentado desde el controlador de vista superior
El ejemplo está en Swift 3.
Hay 3 sobrecargas
//Get the topmost view controller for the current application.
public func MGGetTopMostViewController() -> UIViewController? {
if let currentWindow:UIWindow = UIApplication.shared.keyWindow {
return MGGetTopMostViewController(fromWindow: currentWindow)
}
return nil
}
//Gets the topmost view controller from a specific window.
public func MGGetTopMostViewController(fromWindow window:UIWindow) -> UIViewController? {
if let rootViewController:UIViewController = window.rootViewController
{
return MGGetTopMostViewController(fromViewController: rootViewController)
}
return nil
}
//Gets the topmost view controller starting from a specific UIViewController
//Pass the rootViewController into this to get the apps top most view controller
public func MGGetTopMostViewController(fromViewController viewController:UIViewController) -> UIViewController {
//UINavigationController
if let navigationViewController:UINavigationController = viewController as? UINavigationController {
let viewControllers:[UIViewController] = navigationViewController.viewControllers
if navigationViewController.viewControllers.count >= 1 {
return MGGetTopMostViewController(fromViewController: viewControllers[viewControllers.count - 1])
}
}
//UIPageViewController
if let pageViewController:UIPageViewController = viewController as? UIPageViewController {
if let viewControllers:[UIViewController] = pageViewController.viewControllers {
if viewControllers.count >= 1 {
return MGGetTopMostViewController(fromViewController: viewControllers[0])
}
}
}
//UITabViewController
if let tabBarController:UITabBarController = viewController as? UITabBarController {
if let selectedViewController:UIViewController = tabBarController.selectedViewController {
return MGGetTopMostViewController(fromViewController: selectedViewController)
}
}
//Lastly, Attempt to get the topmost presented view controller
var presentedViewController:UIViewController! = viewController.presentedViewController
var nextPresentedViewController:UIViewController! = presentedViewController?.presentedViewController
//If there is a presented view controller, get the top most prensentedViewController and return it.
if presentedViewController != nil {
while nextPresentedViewController != nil {
//Set the presented view controller as the next one.
presentedViewController = nextPresentedViewController
//Attempt to get the next presented view controller
nextPresentedViewController = presentedViewController.presentedViewController
}
return presentedViewController
}
//If there is no topmost presented view controller, return the view controller itself.
return viewController
}
Esto es lo que funcionó para mí.
Descubrí que a veces el controlador era nulo en la ventana clave, ya que la ventana clave es una cosa del sistema operativo, como una alerta, etc.
+ (UIViewController*)topMostController
{
UIWindow *topWndow = [UIApplication sharedApplication].keyWindow;
UIViewController *topController = topWndow.rootViewController;
if (topController == nil)
{
// The windows in the array are ordered from back to front by window level; thus,
// the last window in the array is on top of all other app windows.
for (UIWindow *aWndow in [[UIApplication sharedApplication].windows reverseObjectEnumerator])
{
topController = aWndow.rootViewController;
if (topController)
break;
}
}
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
return topController;
}
Extensión simple para UIApplication
en Swift:
NOTA:
Se preocupa por moreNavigationController
dentro de UITabBarController
extension UIApplication {
class func topViewController(baseViewController: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? {
if let navigationController = baseViewController as? UINavigationController {
return topViewController(navigationController.visibleViewController)
}
if let tabBarViewController = baseViewController as? UITabBarController {
let moreNavigationController = tabBarViewController.moreNavigationController
if let topViewController = moreNavigationController.topViewController where topViewController.view.window != nil {
return topViewController(topViewController)
} else if let selectedViewController = tabBarViewController.selectedViewController {
return topViewController(selectedViewController)
}
}
if let splitViewController = baseViewController as? UISplitViewController where splitViewController.viewControllers.count == 1 {
return topViewController(splitViewController.viewControllers[0])
}
if let presentedViewController = baseViewController?.presentedViewController {
return topViewController(presentedViewController)
}
return baseViewController
}
}
Uso simple:
if let topViewController = UIApplication.topViewController() {
//do sth with top view controller
}
Gran solución en Swift, implementar en AppDelegate
func getTopViewController()->UIViewController{
return topViewControllerWithRootViewController(UIApplication.sharedApplication().keyWindow!.rootViewController!)
}
func topViewControllerWithRootViewController(rootViewController:UIViewController)->UIViewController{
if rootViewController is UITabBarController{
let tabBarController = rootViewController as! UITabBarController
return topViewControllerWithRootViewController(tabBarController.selectedViewController!)
}
if rootViewController is UINavigationController{
let navBarController = rootViewController as! UINavigationController
return topViewControllerWithRootViewController(navBarController.visibleViewController)
}
if let presentedViewController = rootViewController.presentedViewController {
return topViewControllerWithRootViewController(presentedViewController)
}
return rootViewController
}
Hace poco tuve esta situación en uno de mis proyectos, que requería mostrar una vista de notificación independientemente del tipo de controlador mostrado y del tipo (controlador de control de la imagen, controlador clásico o controlador de vista personalizado), cuando el estado de la red cambió.
Así que juste publiqué mi código, que es bastante fácil y en realidad se basa en un protocolo, por lo que es flexible con cada tipo de controlador de contenedor. Parece estar relacionado con las últimas respuestas, pero de una manera mucho más flexible.
Puede obtener el código aquí: PPTopMostController
Y obtuve el control más alto usando
UIViewController *c = [UIViewController topMostController];
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, se bloquearía, por lo que usaría este código para llegar a la parte superior de todos los controladores de vista modal
UIViewController* parentController =[UIApplication sharedApplication].keyWindow.rootViewController;
while( parentController.presentedViewController &&
parentController != parentController.presentedViewController )
{
parentController = parentController.presentedViewController;
}
Obtener el controlador de vista superior para Swift usando extensiones
Código:
extension UIViewController {
@objc func topMostViewController() -> UIViewController {
// Handling Modal views
if let presentedViewController = self.presentedViewController {
return presentedViewController.topMostViewController()
}
// Handling UIViewController''s added as subviews to some other views.
else {
for view in self.view.subviews
{
// Key property which most of us are unaware of / rarely use.
if let subViewController = view.next {
if subViewController is UIViewController {
let viewController = subViewController as! UIViewController
return viewController.topMostViewController()
}
}
}
return self
}
}
}
extension UITabBarController {
override func topMostViewController() -> UIViewController {
return self.selectedViewController!.topMostViewController()
}
}
extension UINavigationController {
override func topMostViewController() -> UIViewController {
return self.visibleViewController!.topMostViewController()
}
}
Uso:
UIApplication.sharedApplication().keyWindow!.rootViewController!.topMostViewController()
Otra solución más Swift.
func topController() -> UIViewController? {
// recursive follow
func follow(from:UIViewController?) -> UIViewController? {
if let to = (from as? UITabBarController)?.selectedViewController {
return follow(to)
} else if let to = (from as? UINavigationController)?.visibleViewController {
return follow(to)
} else if let to = from?.presentedViewController {
return follow(to)
}
return from
}
let root = UIApplication.sharedApplication().keyWindow?.rootViewController
return follow(root)
}
Para completar la answer de Eric (quienes omitieron las ventanas emergentes, los controles de navegación, los controladores de la barra de navegación, los controladores de vista agregados como subvistas a otros controladores de vista mientras se está cruzando), aquí está mi versión de devolver el controlador de vista actualmente visible:
================================================== ===================
- (UIViewController*)topViewController {
return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)viewController {
if ([viewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)viewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([viewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navContObj = (UINavigationController*)viewController;
return [self topViewControllerWithRootViewController:navContObj.visibleViewController];
} else if (viewController.presentedViewController && !viewController.presentedViewController.isBeingDismissed) {
UIViewController* presentedViewController = viewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
}
else {
for (UIView *view in [viewController.view subviews])
{
id subViewController = [view nextResponder];
if ( subViewController && [subViewController isKindOfClass:[UIViewController class]])
{
if ([(UIViewController *)subViewController presentedViewController] && ![subViewController presentedViewController].isBeingDismissed) {
return [self topViewControllerWithRootViewController:[(UIViewController *)subViewController presentedViewController]];
}
}
}
return viewController;
}
}
================================================== ===================
Y ahora todo lo que necesita hacer para obtener la mayoría de los controladores de vista es llamar al método anterior de la siguiente manera:
UIViewController *topMostViewControllerObj = [self topViewController];
Para completar la answer de JonasG (que dejó de lado los controladores de la barra de pestañas mientras cruzaba), aquí está mi versión de devolver el controlador de vista actualmente visible:
- (UIViewController*)topViewController {
return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)rootViewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController*)rootViewController;
return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
} else if (rootViewController.presentedViewController) {
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
} else {
return rootViewController;
}
}
Para la última versión de Swift:
Cree un archivo, UIWindowExtension.swift
nombre UIWindowExtension.swift
y pegue el siguiente fragmento de UIWindowExtension.swift
:
import UIKit
public extension UIWindow {
public var visibleViewController: UIViewController? {
return UIWindow.getVisibleViewControllerFrom(self.rootViewController)
}
public static func getVisibleViewControllerFrom(vc: UIViewController?) -> UIViewController? {
if let nc = vc as? UINavigationController {
return UIWindow.getVisibleViewControllerFrom(nc.visibleViewController)
} else if let tc = vc as? UITabBarController {
return UIWindow.getVisibleViewControllerFrom(tc.selectedViewController)
} else {
if let pvc = vc?.presentedViewController {
return UIWindow.getVisibleViewControllerFrom(pvc)
} else {
return vc
}
}
}
}
func getTopViewController() -> UIViewController? {
let appDelegate = UIApplication.sharedApplication().delegate
if let window = appDelegate!.window {
return window?.visibleViewController
}
return nil
}
Úsalo en cualquier lugar como:
if let topVC = getTopViewController() {
}
Rápido:
extension UIWindow {
func visibleViewController() -> UIViewController? {
if let rootViewController: UIViewController = self.rootViewController {
return UIWindow.getVisibleViewControllerFrom(rootViewController)
}
return nil
}
class func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController {
if vc.isKindOfClass(UINavigationController.self) {
let navigationController = vc as UINavigationController
return UIWindow.getVisibleViewControllerFrom( navigationController.visibleViewController)
} else if vc.isKindOfClass(UITabBarController.self) {
let tabBarController = vc as UITabBarController
return UIWindow.getVisibleViewControllerFrom(tabBarController.selectedViewController!)
} else {
if let presentedViewController = vc.presentedViewController {
return UIWindow.getVisibleViewControllerFrom(presentedViewController.presentedViewController!)
} else {
return vc;
}
}
}
Uso:
if let topController = window.visibleViewController() {
println(topController)
}
Solución Swift alternativa:
static func topMostController() -> UIViewController {
var topController = UIApplication.sharedApplication().keyWindow?.rootViewController
while (topController?.presentedViewController != nil) {
topController = topController?.presentedViewController
}
return topController!
}
Una versión completa no recursiva, cuidando diferentes escenarios:
- El controlador de vista está presentando otra vista.
- El controlador de vista es un
UINavigationController
- El controlador de vista es un
UITabBarController
C objetivo
UIViewController *topViewController = self.window.rootViewController;
while (true)
{
if (topViewController.presentedViewController) {
topViewController = topViewController.presentedViewController;
} else if ([topViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *nav = (UINavigationController *)topViewController;
topViewController = nav.topViewController;
} else if ([topViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController *tab = (UITabBarController *)topViewController;
topViewController = tab.selectedViewController;
} else {
break;
}
}
Swift 4+
extension UIWindow {
func topViewController() -> UIViewController? {
var top = self.rootViewController
while true {
if let presented = top?.presentedViewController {
top = presented
} else if let nav = top as? UINavigationController {
top = nav.visibleViewController
} else if let tab = top as? UITabBarController {
top = tab.selectedViewController
} else {
break
}
}
return top
}
}
iOS 4 introdujo la propiedad rootViewController en UIWindow:
[UIApplication sharedApplication].keyWindow.rootViewController;
Sin embargo, deberá configurarlo usted mismo después de crear el controlador de vista.
Otra solución se basa en la cadena de respondedores, que puede funcionar o no dependiendo de lo que sea el primer respondedor:
- Consigue el primer respondedor .
- Obtenga el UIViewController asociado con ese primer respondedor .
Ejemplo de pseudo código:
+ (UIViewController *)currentViewController {
UIView *firstResponder = [self firstResponder]; // from the first link above, but not guaranteed to return a UIView, so this should be handled more appropriately.
UIViewController *viewController = [firstResponder viewController]; // from the second link above
return viewController;
}
Si el controlador raíz es un controlador de navegación, la forma correcta de encontrar el controlador visible superior es:
UIViewController *rootVC = [[UIApplication sharedApplication] keyWindow].rootViewController;
if ([rootVC respondsToSelector:@selector(visibleViewController)])
{
UIViewController *topVC = [(UINavigationController *)rootVC visibleViewController];
// do your thing with topVC
}
Aquí hay un extracto de UINavigationController.h:
@property(nonatomic,readonly,retain) UIViewController *topViewController; // The top view controller on the stack.
@property(nonatomic,readonly,retain) UIViewController *visibleViewController; // Return modal view controller if it exists. Otherwise the top view controller.
Usted podría encontrar el controlador de vista más superior utilizando
NSArray *arrViewControllers=[[self navigationController] viewControllers];
UIViewController *topMostViewController=(UIViewController *)[arrViewControllers objectAtIndex:[arrViewControllers count]-1];
Y otra solución rápida.
extension UIViewController {
static var topmostViewController: UIViewController? {
return UIApplication.sharedApplication().keyWindow?.topmostViewController
}
var topmostViewController: UIViewController? {
return presentedViewController?.topmostViewController ?? self
}
}
extension UINavigationController {
override var topmostViewController: UIViewController? {
return visibleViewController?.topmostViewController
}
}
extension UITabBarController {
override var topmostViewController: UIViewController? {
return selectedViewController?.topmostViewController
}
}
extension UIWindow {
var topmostViewController: UIViewController? {
return rootViewController?.topmostViewController
}
}
Esto funciona muy bien para encontrar el controlador de vista superior 1 desde cualquier control de vista raíz
+ (UIViewController *)topViewControllerFor:(UIViewController *)viewController
{
if(!viewController.presentedViewController)
return viewController;
return [MF5AppDelegate topViewControllerFor:viewController.presentedViewController];
}
/* View Controller for Visible View */
AppDelegate *app = [UIApplication sharedApplication].delegate;
UIViewController *visibleViewController = [AppDelegate topViewControllerFor:app.window.rootViewController];
Muchas de estas respuestas son incompletas. Aunque esto está en Objective-C, esta es la mejor compilación de todas las que podría juntar por ahora, como un bloque no recursivo:
... Enlace a gist , en caso de que se revise: https://gist.github.com/benguild/0d149bb3caaabea2dac3d2dca58c0816
... Código de referencia / comparación:
UIViewController *(^topmostViewControllerForFrontmostNormalLevelWindowBlock)(void)=^UIViewController * // NOTE: Adapted from various stray answers here: https://.com/questions/6131205/iphone-how-to-find-topmost-view-controller/20515681
{
__block UIViewController *viewController;
[[[[[UIApplication sharedApplication] windows] reverseObjectEnumerator] allObjects] enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop)
{
if ([window windowLevel]==UIWindowLevelNormal)
{
viewController=[window rootViewController];
////
*stop=YES;
}
} ];
while (viewController)
{
if ([viewController isKindOfClass:[UITabBarController class]])
{
viewController=[(UITabBarController *)viewController selectedViewController];
}
else if ([viewController isKindOfClass:[UINavigationController class]])
{
viewController=[(UINavigationController *)viewController visibleViewController];
}
else if ([viewController presentedViewController] && ![[viewController presentedViewController] isBeingDismissed])
{
viewController=[viewController presentedViewController];
}
else if ([[viewController childViewControllers] count]>0)
{
viewController=[[viewController childViewControllers] lastObject];
}
else
{
__block BOOL needsRepeat=NO;
[[[[[viewController view] subviews] reverseObjectEnumerator] allObjects] enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull view, NSUInteger idx, BOOL * _Nonnull stop)
{
if ([[view nextResponder] isKindOfClass:[UIViewController class]])
{
viewController=(UIViewController *)[view nextResponder];
needsRepeat=YES;
////
*stop=YES;
}
} ];
if (!needsRepeat)
{
break;
}
}
}
return viewController;
};
@implementation UIWindow (Extensions) - (UIViewController*) topMostController { UIViewController *topController = [self rootViewController]; while (topController.presentedViewController) { topController = topController.presentedViewController; } return topController; } @end
- (UIViewController*)topViewController {
return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)rootViewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController*)rootViewController;
return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
} else if (rootViewController.presentedViewController) {
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
} else {
return rootViewController;
}
}