iPhone: mostra UITableViewController modale con barra di navigazione


87

Sto mostrando una vista modale che è una UITableViewControllerclasse. Per qualche motivo non mostrerà la barra di navigazione quando la mostro. Ecco il mio codice:

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

Pensavo fosse mostrato di default? Se aiuta, lo chiamo da un'altra classe UITableViewControllergestita anche da a UINavigationController. Idee?

Risposte:


146

Quando si presenta un controller di visualizzazione modale, non vengono utilizzati controller di navigazione o barre di navigazione esistenti. Se tutto ciò che desideri è visualizzare una barra di navigazione, devi aggiungere la barra di navigazione come sottoview della tua visualizzazione modale e presentarla mentre lo fai.

Se desideri presentare un controller di visualizzazione modale con funzionalità di navigazione, devi presentare un controller di navigazione modale contenente il controller di visualizzazione dei dettagli, in questo modo:

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

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

Il controller modale gestirà il proprio stack di navigazione.


Grazie, apprezzo la spiegazione quindi so cosa avevo fatto di sbagliato.
Nic Hubbard

1
Se usi uno storyboard, non è necessaria alcuna codifica per ottenere ciò. Buona soluzione!
Jelle

36

Ecco un modo per visualizzare la barra di navigazione per coloro che utilizzano gli storyboard, suggerito dal Tutorial su Storyboard di Apple .

Poiché un controller di visualizzazione modale non viene aggiunto allo stack di navigazione, non ottiene una barra di navigazione dal controller di navigazione del controller di visualizzazione tabella. Per fornire al controller di visualizzazione una barra di navigazione quando presentato in modo modale, incorporalo nel suo controller di navigazione.

  1. Nella vista struttura, seleziona Visualizza controller.
  2. Con il controller di visualizzazione selezionato, scegli Editor> Incorpora in> Controller di navigazione.

Assicurati di aggiungere il segue modale al controller di navigazione e non al TableViewController
bickster

Nella situazione della pagina di modifica del profilo utente di Twitter. Questo è un UITableViewController presentato in modo modale e ha i pulsanti FATTO e ANNULLA nella parte superiore. Questa risposta non ha senso semanticamente in quella situazione perché non avviene alcuna navigazione.
William Entriken

17

Su iOS 7 e vuoi solo una barra di navigazione sul tuo controller di visualizzazione modale per mostrare un titolo e alcuni pulsanti? Prova questa magia nel tuo 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];
}

Seam per essere un ottimo modo per fare le cose. ma quando lo provo su un UITableViewController statico, non sono più in grado di scorrere la tableview. qualche idea del perché?
Thomas Besnehard

2
al giorno d'oggi sarebbe meglio incorporarlo in un controller di navigazione.
malhal

Questa è una bella soluzione, ma un piccolo problema è che quando scorri i titoli dell'intestazione della cella vengono visualizzati nella parte superiore della barra di navigazione.
Ali

L'ho risolto aggiungendo [self.view bringSubviewToFront:self.navigationBar];alla fine di -(void)layoutNavigationBar.
Ali

7

Voglio condividere come la soluzione accettata può essere utilizzata nei progetti con storyboard:

L'approccio semplice consiste nell'inserire un controller di navigazione vuoto dello storyboard prima del VC che deve essere presentato in modo modale, quindi le relazioni assomigliano a:

(Presenter VC) -> presenta in modo modale -> (controller di navigazione con un controller da presentare come root).

Abbiamo provato questo approccio per un po 'e abbiamo notato che i nostri storyboard vengono "inquinati" da un gran numero di tali controller di navigazione intermedi quando ciascuno! di loro è utilizzato esclusivamente per uno! presentazione di qualche altro controller, che vogliamo venga presentato in modo modale con barra di navigazione.

La nostra soluzione attuale consiste nell'incapsulare il codice dalla risposta accettata a un segue personalizzato:

#import "ModalPresentationWithNavigationBarSegue.h"

@implementation ModalPresentationWithNavigationBarSegue

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

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

Avendo questo segue nel nostro progetto non creiamo più controller di navigazione intermedi nei nostri storyboard, usiamo solo questo ModalPresentationWithNavigationBarSegue come:

Presentatore VC -> Presentee VC

Spero che questa risposta sia utile alle persone a cui piace evitare inutili duplicazioni negli storyboard delle loro app.


5

Se è necessario solo un NavigationBar, è possibile aggiungere un'istanza di UINavigationBare assegnarvi BarItems.


Dipende dal ViewController: penso che non puoi aggiungere un UINavigationBar a un UITableViewController, vero?
Tobias

In IB, vai su Editor -> Incorpora nel controller di navigazione e avrai una barra di navigazione. Trascina e aggiungi BarButtonItems a quello.
AmitaiB

5

Volevo solo aggiungere qualcosa a ciò che ha detto @Scott. La sua risposta è sicuramente il modo più semplice e più accettato per farlo ora con Storyboard, iOS 7 e 8 ... (e presto, 9).

Sicuramente l'aggiunta di un controller di visualizzazione allo Storyboard e l'incorporamento come descritto da @Scott è la strada giusta.

Quindi, aggiungi semplicemente il segue trascinando il controllo dal controller della vista di origine alla destinazione (quello che vuoi mostrare in modo modale), seleziona "Presenta in modo modale" quando appare la piccola vista con le scelte per il tipo di segue. Probabilmente va bene anche dargli un nome (nell'esempio sotto uso "presentMyModalViewController").

Una cosa di cui avevo bisogno che mancava è che il caso di @ Scott è quando si desidera effettivamente passare alcuni dati a quel controller di visualizzazione presentato in modo modale che è incorporato nel controller di navigazione.

Se prendi il segue.destinationViewController, sarà un UINavigationController, non il controller che hai incorporato in UINavigationController.

Quindi, per accedere al controller di visualizzazione incorporato all'interno del controller di navigazione, ecco cosa ho fatto:

- (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!";
    }
}

Spero che sia di aiuto!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.