Текущий вид контроллера из AppDelegate? - PullRequest
50 голосов
/ 26 января 2012

Есть ли способ получить текущий контроллер вида из AppDelegate? Я знаю, что есть rootViewController, но это не то, что я ищу.

Ответы [ 10 ]

61 голосов
/ 03 сентября 2013

Если контроллер представления вашего приложения - UINavigationController, вы можете сделать это:

((UINavigationController*)appDelegate.window.rootViewController).visibleViewController;

Аналогично, если это UITabBarController, вы можете сделать это:

((UITabBarController*)appDelegate.window.rootViewController).selectedViewController;

Конечно, явное приведение типа этого грязно. Лучше было бы захватить ссылку самостоятельно, используя сильные типы.

26 голосов
/ 17 июня 2015

Это может помочь

- (UIViewController *)topViewController{
  return [self topViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}

- (UIViewController *)topViewController:(UIViewController *)rootViewController
{
  if (rootViewController.presentedViewController == nil) {
    return rootViewController;
  }

  if ([rootViewController.presentedViewController isKindOfClass:[UINavigationController class]]) {
    UINavigationController *navigationController = (UINavigationController *)rootViewController.presentedViewController;
    UIViewController *lastViewController = [[navigationController viewControllers] lastObject];
    return [self topViewController:lastViewController];
  }

  UIViewController *presentedViewController = (UIViewController *)rootViewController.presentedViewController;
  return [self topViewController:presentedViewController];
}

Версия Swift:

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
    }
}

Взято из: https://gist.github.com/snikch/3661188

20 голосов
/ 26 января 2012

Если у вас есть UINavigationController в appDelegate, используйте его свойство topViewController или visibleViewController

14 голосов
/ 11 февраля 2016

Сделать расширение:

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

            if let top = moreNavigationController.topViewController where top.view.window != nil {
                return topViewController(top)
            } else if let selected = tab.selectedViewController {
                return topViewController(selected)
            }
        }
        if let presented = base?.presentedViewController {
            return topViewController(presented)
        }
        return base
    }
}

Использование:

if let rootViewController = UIApplication.topViewController() {
    //do sth with root view controller
}
11 голосов
/ 26 января 2012

Получить объект appDelegate:

MyAppDelegate *tmpDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];

Как предположил Бериллий, вы можете использовать свойства UINavigationController для доступа к вашему текущему контроллеру представления.

Таким образом, код будет выглядеть так:

id myCurrentController = tmpDelegate.myNavigationController.topViewController;

или

NSArray *myCurrentViewControllers = tmpDelegate.myNavigationController.viewControllers;
8 голосов
/ 13 июля 2015

Вы можете получить текущий контроллер представления от rootViewController, ища его представленный ViewController, например:

UIViewController *parentViewController = [[[UIApplication sharedApplication] delegate] window].rootViewController;

while (parentViewController.presentedViewController != nil){
    parentViewController = parentViewController.presentedViewController;
}
UIViewController *currentViewController = parentViewController;

Это работает со мной.Надеюсь, это поможет:)

4 голосов
/ 21 августа 2015

Быстрое решение:

 self.window.rootViewController.presentedViewController. 

Это должно дать вам то, что вам нужно.

4 голосов
/ 30 апреля 2015

Для всех не , использующих UINavigationController, а вместо этого их контроллер представления по умолчанию - UIViewController, вы можете проверить, какой контроллер представления активен (или представлен), с помощью следующего в AppDelegate:

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
    if let rootViewController = self.window!.rootViewController {
        if let presentedViewController = rootViewController.presentedViewController {
            return presentedViewController.supportedInterfaceOrientations()
        }
    } // Else current view controller is DefaultViewController

    return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}

Как вы можете видеть, я проверяю текущий контроллер вида, чтобы поддерживать различные ориентации интерфейса для определенных контроллеров вида.Для всех, кто заинтересован в использовании этого метода для поддержки конкретных, в каждом контроллере представления, который нуждается в определенной ориентации, должно быть размещено следующее:

override func supportedInterfaceOrientations() -> Int {
    return Int(UIInterfaceOrientationMask.All.rawValue)
} 

Примечание: Этот код был написан с использованием Swift 1.2

1 голос
/ 22 апреля 2019

Расширение UIApplication в Swift 4 + синтаксис на основе решения A.G

public 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 {
            let moreNavigationController = tab.moreNavigationController

            if let top = moreNavigationController.topViewController, top.view.window != nil {
                return topViewController(base: top)
            } else if let selected = tab.selectedViewController {
                return topViewController(base: selected)
            }
        }
        if let presented = base?.presentedViewController {
            return topViewController(base: presented)
        }
        return base
    }
}

Пример использования:

if let rootViewController = UIApplication.topViewController() {
     //do something with rootViewController
}
0 голосов
/ 14 сентября 2017

Часто мне нужно получить контроллер представления, который отображается в данный момент.Это может означать контроллер представления в верхней части стека текущего UINavigationController, представленный в настоящее время контроллер представления и т. Д. Поэтому я написал эту функцию, которая вычисляет ее большую часть времени, и которую можно использовать внутри расширения UIViewController.

Код в Swift 3 :

func currentViewController(
_ viewController: UIViewController? =
    UIApplication.shared.keyWindow?.rootViewController)
        -> UIViewController? {
    guard let viewController =
    viewController else { return nil }

    if let viewController =
        viewController as? UINavigationController {
        if let viewController =
            viewController.visibleViewController {
            return currentViewController(viewController)
        } else {
            return currentViewController(
                viewController.topViewController)
        }
    } else if let viewController =
            viewController as? UITabBarController {
        if let viewControllers =
            viewController.viewControllers,
            viewControllers.count > 5,
            viewController.selectedIndex >= 4 {
            return currentViewController(
                viewController.moreNavigationController)
        } else {
            return currentViewController(
                viewController.selectedViewController)
        }
    } else if let viewController =
            viewController.presentedViewController {
        return viewController
    } else if viewController.childViewControllers.count > 0 {
        return viewController.childViewControllers[0]
    } else {
        return viewController
    }
}

Позвоните по номеру: currentViewController()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...