Donc, je pousse un contrôleur de vue de RootViewController comme:
[self.navigationController pushViewController: anotherViewController animé: OUI];
MAIS, DE anotherViewController
maintenant, je veux accéder à nouveau à RootViewController.
J'essaie
// (dans anotherViewController maintenant) /// RootViewController * root = (RootViewController *) self.parentViewController; // N ° // err RootViewController * root = (RootViewController *) [self.navigationController.viewControllers objectAtIndex: 0]; // OUI!! Ça marche
Je ne suis pas sûr pourquoi cela fonctionne et je ne suis pas sûr que ce soit la meilleure façon de le faire. Quelqu'un peut-il commenter un meilleur moyen d'obtenir le RootViewController à partir d'un contrôleur que vous avez inséré dans navigationController de ce RootViewController, et de déterminer si la méthode utilisée est fiable ou non?
Utilisez la propriété viewControllers de UINavigationController. Exemple de code:
// Inside another ViewController
NSArray *viewControllers = self.navigationController.viewControllers;
UIViewController *rootViewController = [viewControllers objectAtIndex:viewControllers.count - 2];
C'est le moyen standard d'obtenir le contrôleur de vue "arrière". La raison objectAtIndex:0
_ fonctionne parce que le contrôleur de vue auquel vous essayez d'accéder est également le contrôleur racine. Si vous étiez plus en profondeur dans la navigation, la vue arrière ne serait pas la même que la vue racine.
Version rapide:
var rootViewController = self.navigationController?.viewControllers.first
Version d'ObjectiveC:
UIViewController *rootViewController = [self.navigationController.viewControllers firstObject];
Où self est une instance d'un UIViewController intégré à un UINavigationController.
Une version un peu moins laide de la même chose mentionnée dans à peu près toutes ces réponses:
UIViewController *rootViewController = [[self.navigationController viewControllers] firstObject];
dans votre cas, je ferais probablement quelque chose comme:
dans votre sous-classe UINavigationController :
- (UIViewController *)rootViewController
{
return [[self viewControllers] firstObject];
}
alors vous pouvez utiliser:
UIViewController *rootViewController = [self.navigationController rootViewController];
modifier
OP a demandé une propriété dans les commentaires.
si vous voulez, vous pouvez y accéder via quelque chose comme self.navigationController.rootViewController
en ajoutant simplement une propriété readonly à votre en-tête:
@property (nonatomic, readonly, weak) UIViewController *rootViewController;
Pour tous ceux qui sont intéressés par une extension Swift, voici ce que j'utilise maintenant:
extension UINavigationController {
var rootViewController : UIViewController? {
return self.viewControllers.first as? UIViewController
}
}
En complément de @ dulgan's , il est toujours bon d’utiliser firstObject
sur objectAtIndex:0
, car si le premier retourne nil s'il n'y a pas d'objet dans le tableau, le dernier jette une exception.
UIViewController *rootViewController = self.navigationController.rootViewController;
Sinon, ce serait un gros plus pour vous de créer une catégorie nommée UINavigationController+Additions
et définissez votre méthode en cela.
@interface UINavigationController (Additions)
- (UIViewController *)rootViewController;
@end
@implementation UINavigationController (Additions)
- (UIViewController *)rootViewController
{
return self.viewControllers.firstObject;
}
@end
Que diriez-vous de demander au IApplicationsingleton pour son keyWindow , et à partir de cela IWindow demandez le contrôleur de vue racine (son rootViewController propriété):
UIViewController root = [[[UIApplication sharedApplication] keyWindow] rootViewController];
Ici, je suis venu avec une méthode universelle pour naviguer de n'importe quel endroit à la racine.
Vous créez un nouveau fichier de classe avec cette classe, de sorte qu'il soit accessible de n'importe où dans votre projet:
import UIKit
class SharedControllers
{
static func navigateToRoot(viewController: UIViewController)
{
var nc = viewController.navigationController
// If this is a normal view with NavigationController, then we just pop to root.
if nc != nil
{
nc?.popToRootViewControllerAnimated(true)
return
}
// Most likely we are in Modal view, so we will need to search for a view with NavigationController.
let vc = viewController.presentingViewController
if nc == nil
{
nc = viewController.presentingViewController?.navigationController
}
if nc == nil
{
nc = viewController.parentViewController?.navigationController
}
if vc is UINavigationController && nc == nil
{
nc = vc as? UINavigationController
}
if nc != nil
{
viewController.dismissViewControllerAnimated(false, completion:
{
nc?.popToRootViewControllerAnimated(true)
})
}
}
}
Utilisation de n'importe où dans votre projet:
{
...
SharedControllers.navigateToRoot(self)
...
}