139 votes

Comment obtenir le RootViewController à partir d'un contrôleur poussé ?

Donc, je pousse un contrôleur de vue depuis RootViewController comme :

\[self.navigationController pushViewController:anotherViewController animated:YES\] ;

MAIS, DE anotherViewController maintenant, je veux accéder au RootViewController à nouveau.

J'essaie

// (inside anotherViewController now)
///RootViewController \*root = (RootViewController\*)self.parentViewController ; // No.
// err
RootViewController \*root = (RootViewController\*)\[self.navigationController.viewControllers objectAtIndex:0\] ; // YES!! it works

Je ne suis pas sûr que cela fonctionne et je ne suis pas sûr que ce soit la meilleure façon de le faire. Quelqu'un peut-il me dire s'il existe une meilleure façon d'obtenir le RootViewController d'un contrôleur que vous avez poussé dans le NavigationController de ce RootViewController et si la façon dont je l'ai fait est fiable ou non ?

0 votes

Ce que vous avez fait permettra d'obtenir de manière fiable le contrôleur de vue Root (le premier dans la hiérarchie de navigation), si vous voulez obtenir l'accès au contrôleur de vue "back", voir ma réponse.

182voto

dulgan Points 1707

Version Swift :

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é dans un UINavigationController.

0 votes

Puis-je obtenir le navigationController d'un autre ViewController à partir d'une classe différente ?

0 votes

Toute sous-classe de UIViewController aura une propriété navigationController, qui pointe vers son premier parentViewController correspondant à la classe UINavigationController.

136voto

Benoit Points 39210

Utilisez le viewControllers de l'UINavigationController. Exemple de code :

// Inside another ViewController
NSArray *viewControllers = self.navigationController.viewControllers;
UIViewController *rootViewController = [viewControllers objectAtIndex:viewControllers.count - 2];

C'est la façon standard d'obtenir le contrôleur de vue "arrière". La raison pour laquelle objectAtIndex:0 est dû au fait que le contrôleur de vue auquel vous essayez d'accéder est également celui de la racine. Si vous vous trouviez plus loin dans la navigation, la vue arrière ne serait pas la même que la vue racine.

6 votes

:) ty. Ça semble toujours aussi bricolé - :) Je voulais vraiment un membre "officiel" pour faire le travail, quelque chose comme self.navigationController.rootViewController, mais hélas, rien de tel

62 votes

Le code ci-dessus est erroné. rootViewController est absent * avant lui, et l'index devrait juste être 0 . Le code dans la question est correct : RootViewController *root = (RootViewController *)[navigationController.viewControllers objectAtIndex:0]

2 votes

D'accord : le code ci-dessus renvoie le parent et non le contrôleur de vue Raíz contrôleur de vue comme le demande le PO. Pourtant, c'est ce que Ben S a dit qu'il ferait, mais il ne l'a pas assez souligné.

12voto

Jesse Points 3520

Une version légèrement moins laide de la même chose que celle mentionnée dans presque 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];

editar

L'OP a demandé une propriété dans les commentaires.

si vous le souhaitez, vous pouvez y accéder via quelque chose comme self.navigationController.rootViewController en ajoutant simplement une propriété en lecture seule à votre en-tête :

@property (nonatomic, readonly, weak) UIViewController *rootViewController;

9voto

csch Points 1365

Pour tous ceux qui sont intéressés par une extension swift, c'est ce que j'utilise actuellement :

extension UINavigationController {
    var rootViewController : UIViewController? {
        return self.viewControllers.first
    }
}

3voto

ozgurv Points 509

En complément de @dulgan's réponse, c'est toujours une bonne approche d'utiliser firstObject sur objectAtIndex:0 car si la première renvoie nil s'il n'y a pas d'objet dans le tableau, la seconde lève une exception.

UIViewController *rootViewController = self.navigationController.rootViewController;

Sinon, vous pourriez créer une catégorie appelée UINavigationController+Additions et définissez votre méthode dans celle-ci.

@interface UINavigationController (Additions)

- (UIViewController *)rootViewController;

@end

@implementation UINavigationController (Additions)

- (UIViewController *)rootViewController
{
    return self.viewControllers.firstObject;
}

@end

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X