2010-12-04 4 views
9

La fenêtre principale de mon application contient un UITabBarController basé sur xib (entièrement configuré dans Interface Builder) qui peut également être présenté de manière modale (comme la vue modale Music.app "Ajouter des morceaux à la playlist") . UITabBarController contient un certain nombre de UINavigationControllers qui à leur tour contiennent des UITableViewControllers sous-classés. Voici comment je détecte actuellement si le UITableViewController est présentée sous-classé dans un UITabBarController modal:Déterminer si un UIViewController est présenté de manière modale

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    self.isModal = NO; 

    UIViewController *child  = self; 
    UIViewController *parent = self.parentViewController; 
    while (parent) { 
     if (parent.modalViewController && parent.modalViewController == child) { 
      self.isModal = YES; 
      break; 
     } 
     child = parent; 
     parent = parent.parentViewController; 
    } 

    if (self.isModal) { 
     // modal additions, eg. Done button, navigationItem.prompt 
    } 
    else { 
     // normal additions, eg. Now Playing button 
    } 
} 

Est-il possible de le faire qui n'implique pas marcher l'arbre parentViewController ou sous-classement toute la vue intermédiaire les contrôleurs de transmettre l'état isModal lorsqu'ils sont initialisés?

Répondre

4

Got an answer on Twitter. J'ai fini par sous-classer UITabBarController et ajouter une propriété d'instance BOOL isModal qui est définie sur YES lors de la présentation modale. Les sous-vues peuvent ensuite utiliser self.tabBarController avec une conversion à la sous-classe pour accéder à la propriété isModal et afficher/se comporter en conséquence.

+3

Coulée en sous-classe. Cela semble gênant. Pourquoi sous-classe? Pourquoi ne pas ajouter une catégorie à UITabBarController qui contient isModal? –

1

Vous pouvez définir l'état d'affichage dans un initialiseur personnalisé lorsque vous présentez la vue. Je veux dire que le code qui le présente va savoir comment il est présenté, n'est-ce pas?

- (void)initInModalMode:(BOOL)isModal 

Vaut-il mieux que la vue découvre rétroactivement son statut plus tard?

+0

Il sait qu'il présente un UITabBarController mais il ne le sait pas présente la UITableViewController sous-classé (qui est présenté par l'un des nombreux intermédiaires UINavigationControllers présenté par le UITabBarController) qui a réellement besoin de savoir si elle est présentée modalement ou non. Cette approche ne m'obligerait-elle pas à sous-classer tous les contrôleurs de vues intermédiaires autrement stockés pour s'assurer que la valeur isModal obtient la vue nécessaire? –

2

Je chercherais à obtenir le contrôleur de vue racine et vérifier s'il a un contrôleur de vue modale. Vous pouvez obtenir ce contrôleur de vue à partir de UIWindow. Notez également que vous pouvez parcourir la hiérarchie du contrôleur de vue en cours à l'aide de la propriété viewControllers de UINavigationController: for (UIViewController * viewController dans self.navigationController.viewControllers) {...} est plus rapide et plus simple.

+0

Je ne comprends pas comment une suggestion se connecte à ma question (ne pas dire qu'ils ne le font pas, je ne comprends tout simplement pas). Si un bouton dans UIWindow> UITabBarController> UINavigationBarController> ACustomTableViewController présente la même hiérarchie UITabBarController de manière modale, comment le contrôleur racine UITabBarController dans UIWindow sait-il ce qui se passe? En ce qui concerne self.navigationController.viewControllers, cela ne contient-il pas simplement la hiérarchie dans le fichier currentController? Comment cela m'aide-t-il dans la vue modale qui présente une instance distincte du même UITabBarController? –

+0

Lorsque vous chargez votre UITabBarController, si c'est le rootViewController de l'UIWindow actuelle, vous ne placez pas le bouton Done dans l'interface utilisateur. Sinon, il va être au-dessus de rootViewController (probablement modal, mais vous devriez vérifier pour être sûr.) Vous pensez en termes de hiérarchie de vue actuelle ... – chockenberry

+0

L'autre commentaire sur l'itération à travers les contrôleurs de vue était juste pour vous montrer que vous n'a pas besoin de vérifier les parents, etc. Cela n'aide pas le problème de savoir si vous êtes modal ou non. – chockenberry

10

Si vous une recherche d'iOS 6 +, cette réponse est dépréciée et vous devriez vérifier Gabriele Petronella's answer


je répondu à une question très similaire il y a quelque temps, où j'ai une fonction pour déterminer si la régulateur de courant est présenté comme modal ou non, sans la nécessité de sous-classe le contrôleur de barre d'onglets ici:

Is it possible to determine whether ViewController is presented as Modal?

au rép d'origine heu il y a quelques explications sur la façon dont cette fonction et vous CANcheck là si nécessaire, mais ici il est

-(BOOL)isModal { 

    BOOL isModal = ((self.parentViewController && self.parentViewController.modalViewController == self) || 
      //or if I have a navigation controller, check if its parent modal view controller is self navigation controller 
      (self.navigationController && self.navigationController.parentViewController && self.navigationController.parentViewController.modalViewController == self.navigationController) || 
      //or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation 
      [[[self tabBarController] parentViewController] isKindOfClass:[UITabBarController class]]); 

    //iOS 5+ 
    if (!isModal && [self respondsToSelector:@selector(presentingViewController)]) { 

     isModal = ((self.presentingViewController && self.presentingViewController.modalViewController == self) || 
      //or if I have a navigation controller, check if its parent modal view controller is self navigation controller 
      (self.navigationController && self.navigationController.presentingViewController && self.navigationController.presentingViewController.modalViewController == self.navigationController) || 
      //or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation 
      [[[self tabBarController] presentingViewController] isKindOfClass:[UITabBarController class]]); 

    } 

    return isModal;   

} 
4

Depuis iOS5, vous pouvez également utiliser isBeingPresented sur une instance viewController:

- (BOOL)isModalViewController 
{ 
    return [self isBeingPresented]; 
} 
0

Il y a un moyen beaucoup plus facile dans ces jours Swift.

extension UIViewController { 

    var isPresentedModally: Bool { 
     return presentingViewController?.presentedViewController == self || parent?.isPresentedModally == true 
    } 

}