web-dev-qa-db-fra.com

iPhone: afficher le modal UITableViewController avec la barre de navigation

Je montre une vue modale qui est une classe UITableViewController. Pour une raison quelconque, la barre de navigation ne s'affichera pas lorsque je la montrerai. Voici mon code:

SettingsCreateAccount *detailViewController = [[SettingsCreateAccount alloc] initWithStyle:UITableViewStyleGrouped];
    detailViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    detailViewController.navigationController.navigationBarHidden = NO;
    [self.navigationController presentModalViewController:detailViewController animated:YES];
    detailViewController = nil;
    [detailViewController release];

Je pensais que c'était montré par défaut? Si cela aide, je l'appelle à partir d'une autre classe qui est également un UITableViewController géré par un UINavigationController. Des idées?

86
Nic Hubbard

Lorsque vous présentez un contrôleur de vue modale, il n'utilise aucun contrôleur de navigation ou barre de navigation existant. Si tout ce que vous voulez, c'est afficher une barre de navigation, vous devez l'ajouter en tant que sous-vue de votre vue modale et la présenter comme vous le faites.

Si vous souhaitez présenter un contrôleur de vue modale avec des fonctionnalités de navigation, vous devez plutôt présenter un contrôleur de navigation modale contenant votre contrôleur de vue détaillée, comme suit:

SettingsCreateAccount *detailViewController = [[SettingsCreateAccount alloc] initWithStyle:UITableViewStyleGrouped];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
[detailViewController release];

navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:navController animated:YES];
[navController release];

Votre contrôleur modal gérera sa propre pile de navigation.

144
BoltClock

Voici une façon d'afficher la barre de navigation pour ceux qui utilisent des storyboards, suggérée par Apple's Tutorial on Storyboard .

Étant donné qu'un contrôleur de vue modale n'est pas ajouté à la pile de navigation, il ne reçoit pas de barre de navigation du contrôleur de navigation du contrôleur de vue de table. Pour donner au contrôleur de vue une barre de navigation lorsqu'il est présenté de manière modale, incorporez-le dans son propre contrôleur de navigation.

  1. Dans la vue hiérarchique, sélectionnez Afficher le contrôleur.
  2. Avec le contrôleur de vue sélectionné, choisissez Éditeur> Incorporer dans> Contrôleur de navigation.
36
Scott

Sur iOS 7 et vous voulez juste une barre de navigation sur votre contrôleur de vue modale pour afficher un titre et quelques boutons? Essayez cette magie dans votre UITableViewController:

// in the .h
@property (strong) UINavigationBar* navigationBar;

//in the .m
- (void)viewDidLoad {
    [super viewDidLoad];

    self.navigationItem.title = @"Awesome";
    self.navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectZero];
    [self.view addSubview:_navigationBar];
    [self.navigationBar pushNavigationItem:self.navigationItem animated:NO];
}

-(void)layoutNavigationBar{
    self.navigationBar.frame = CGRectMake(0, self.tableView.contentOffset.y, self.tableView.frame.size.width, self.topLayoutGuide.length + 44);
    self.tableView.contentInset = UIEdgeInsetsMake(self.navigationBar.frame.size.height, 0, 0, 0);
}

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    //no need to call super
    [self layoutNavigationBar];
}

-(void)viewDidLayoutSubviews{
    [super viewDidLayoutSubviews];
    [self layoutNavigationBar];
}
17
malhal

Je veux partager comment la solution acceptée peut être utilisée dans des projets avec des storyboards:

L'approche simple consiste à mettre un contrôleur de navigation vide de storyboard avant le VC qui doit être présenté de manière modale, de sorte que les relations ressemblent à:

(Presenter VC) -> présente de façon modale -> (contrôleur de navigation ayant un contrôleur à présenter comme racine).

Nous avons essayé cette approche pendant un certain temps et avons remarqué que nos story-boards deviennent "pollués" par un grand nombre de ces contrôleurs de navigation intermédiaires quand chacun! d'entre eux est utilisé exclusivement pour un! présentation d'un autre contrôleur, que nous souhaitons présenter de façon modale avec la barre de navigation.

Notre solution actuelle consiste à encapsuler le code de la réponse acceptée à une séquence personnalisée:

#import "ModalPresentationWithNavigationBarSegue.h"

@implementation ModalPresentationWithNavigationBarSegue

- (void)perform {
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.destinationViewController];

    [self.sourceViewController presentViewController:navigationController animated:YES completion:nil];
}
@end

Ayant cette séquence dans notre projet, nous ne créons plus de contrôleurs de navigation intermédiaires dans nos storyboards, nous utilisons simplement ce ModalPresentationWithNavigationBarSegue comme:

Présentateur VC -> VC présenté

J'espère que cette réponse sera utile aux personnes qui aiment éviter les doublons inutiles dans leurs storyboards d'applications.

7

Je voulais juste ajouter quelque chose à ce que @Scott a dit. Sa réponse est certainement la façon la plus simple et la plus acceptée de le faire maintenant avec les storyboards, iOS 7 et 8 ... (et bientôt, 9).

Certainement ajouter un contrôleur de vue au Storyboard et l'incorporer comme décrit par @Scott est la bonne façon de procéder.

Ensuite, ajoutez simplement la séquence en faisant glisser la commande du contrôleur de vue source vers la cible (celle que vous souhaitez afficher de manière modale), sélectionnez "Présenter modalement" lorsque la petite vue apparaît avec les choix pour le type de séquence. Probablement bien de lui donner un nom aussi (dans l'exemple ci-dessous, j'utilise "presentMyModalViewController").

Une chose dont j'avais besoin qui manquait est le cas de @ Scott, c'est quand vous voulez réellement transmettre certaines données à ce contrôleur de vue présenté de façon modale qui est intégré dans le contrôleur de navigation.

Si vous saisissez le segue.destinationViewController, ce sera un UINavigationController, pas le contrôleur que vous avez incorporé dans le UINavigationController.

Donc, pour accéder au contrôleur de vue intégré à l'intérieur du contrôleur de navigation, voici ce que j'ai fait:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"presentMyModalViewController"]) {
        // This could be collapsed, but it's a little easier to see
        // what's going on written out this way.

        // First get the destination view controller, which will be a UINavigationController
        UINavigationController *nvc = (UINavigationController *)segue.destinationViewController;

        // To get the view controller we're interested in, grab the navigation controller's "topViewController" property
        MyModalViewController *vc = (EmailReceiptViewController *)[nvc topViewController];

        // Now that we have the reference to our view controller, we can set its properties here:
        vc.myAwesomeProperty = @"awesome!";
    }
}

J'espère que cela t'aides!

5
Evan Stone

Si vous n'avez besoin que d'un NavigationBar, vous pouvez ajouter une instance de UINavigationBar et lui affecter des BarItems.

5
xhan