web-dev-qa-db-fra.com

Contrôleur de vue actuel d'AppDelegate?

Existe-t-il un moyen d'obtenir le contrôleur de vue actuel à partir de AppDelegate? Je sais qu'il existe rootViewController, mais ce n'est pas ce que je recherche.

47
aoakenfo

Si vous avez UINavigationController dans appDelegate, utilisez sa propriété topViewController ou visibleViewController

20
beryllium

Si le contrôleur de vue racine de votre application est une UINavigationController, vous pouvez procéder comme suit:

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

De même, s'il s'agit d'une UITabBarController, vous pouvez faire ceci:

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

Bien sûr, un casting explicite comme celui-ci est sale. Le mieux serait de capturer la référence vous-même en utilisant des types forts.

60
devios1

Cela pourrait aider

- (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];
}

Version rapide:

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

Extrait de: https://Gist.github.com/snikch/3661188

25
Daniel Ryan

Faire une extension:

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

Utilisation:

if let rootViewController = UIApplication.topViewController() {
    //do sth with root view controller
}
13
A.G

Obtenez l'objet appDelegate:

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

Comme suggéré par Beryllium, vous pouvez utiliser les propriétés du contrôleur UINavigationController pour accéder à votre contrôleur de vue actuel.

Donc, le code ressemblerait à ceci:

id myCurrentController = tmpDelegate.myNavigationController.topViewController;

ou:

NSArray *myCurrentViewControllers = tmpDelegate.myNavigationController.viewControllers;
11
Quasar

Vous pouvez obtenir le contrôleur de vue actuel à partir de rootViewController en cherchant le programme presentsViewController, comme ceci:

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

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

Ça marche avec moi J'espère que ça aide :)

8
MattZ

Solution rapide:

 self.window.rootViewController.presentedViewController. 

Cela devrait vous donner ce dont vous avez besoin.

4

Pour quiconque pas utilisant un UINavigationController mais son contrôleur de vue par défaut est un UIViewController, vous pouvez vérifier quel contrôleur de vue est actif (ou présenté) avec les éléments suivants dans 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)
}

Comme vous pouvez le constater, je vérifie le contrôleur de vue actuel afin de prendre en charge différentes orientations d'interface pour des contrôleurs de vue spécifiques. Pour toute autre personne intéressée par l'utilisation de cette méthode pour prendre en charge des éléments spécifiques, les éléments suivants doivent être placés dans chaque contrôleur de vue nécessitant une orientation spécifique.

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

Remarque: Ce code a été écrit avec Swift 1.2

4
Clay Ellis

J'ai souvent besoin de récupérer le contrôleur de vue actuellement affiché. Cela pourrait signifier le contrôleur de vue situé en haut de la pile du contrôleur UINavigationController actuel, le contrôleur de vue actuellement présenté, etc. J'ai donc écrit cette fonction qui la définit la plupart du temps et que vous pouvez utiliser à l'intérieur d'une extension UIViewController.

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

Appelez-le avec: currentViewController()

0
Paolo Musolino

Extension d'UIApplication dans Swift 4+ syntaxe basée sur la solution de 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
    }
}

Exemple d'utilisation:

if let rootViewController = UIApplication.topViewController() {
     //do something with rootViewController
}
0
Maverick