iPhone: Modalen UITableViewController mit Navigationsleiste anzeigen

87

Ich zeige eine modale Ansicht, die eine UITableViewControllerKlasse ist. Aus irgendeinem Grund wird die Navigationsleiste nicht angezeigt, wenn ich sie zeige. Hier ist mein Code:

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

Ich dachte, es wurde standardmäßig angezeigt? Wenn es hilft, rufe ich dies aus einer anderen Klasse auf, die ebenfalls von a UITableViewControllerverwaltet wird UINavigationController. Ideen?

Nic Hubbard
quelle

Antworten:

146

Wenn Sie einen Modal View Controller präsentieren, werden keine vorhandenen Navigationscontroller oder Navigationsleisten verwendet. Wenn Sie lediglich eine Navigationsleiste anzeigen möchten, müssen Sie die Navigationsleiste als Unteransicht Ihrer modalen Ansicht hinzufügen und währenddessen anzeigen.

Wenn Sie einen Modal View Controller mit Navigationsfunktionen präsentieren möchten, müssen Sie stattdessen einen Modal Navigation Controller mit Ihrem Detail View Controller präsentieren:

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

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

Ihr Modal Controller verwaltet seinen eigenen Navigationsstapel.

BoltClock
quelle
Danke, ich schätze die Erklärung, damit ich weiß, was ich falsch gemacht habe.
Nic Hubbard
1
Wenn Sie ein Storyboard verwenden, ist dafür überhaupt keine Codierung erforderlich. Gute Lösung!
Jelle
36

Hier ist eine Möglichkeit, die Navigationsleiste für diejenigen anzuzeigen, die Storyboards verwenden, wie in Apples Tutorial auf Storyboard vorgeschlagen .

Da ein Modal View Controller nicht zum Navigationsstapel hinzugefügt wird, erhält er keine Navigationsleiste vom Navigationscontroller des Table View Controllers. Um dem Ansichtscontroller bei modaler Darstellung eine Navigationsleiste zu geben, binden Sie ihn in einen eigenen Navigationscontroller ein.

  1. Wählen Sie in der Gliederungsansicht View Controller aus.
  2. Wählen Sie bei ausgewähltem Ansichts-Controller Editor> Einbetten> Navigations-Controller.
Scott
quelle
Stellen Sie sicher, dass Sie den Modal Segue zum Navigation Controller und nicht zum TableViewController hinzufügen
Bickster
In der Situation von Twitter Benutzerprofilseite bearbeiten. Dies ist ein modal dargestellter UITableViewController mit den Tasten FERTIG und ABBRECHEN oben. Diese Antwort macht in dieser Situation semantisch keinen Sinn, da keine Navigation stattfindet.
William Entriken
17

Unter iOS 7 möchten Sie nur eine Navigationsleiste auf Ihrem Modal View Controller, in der ein Titel und einige Schaltflächen angezeigt werden? Probieren Sie diese Magie in Ihrem UITableViewController aus:

// 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];
}
malhal
quelle
Naht eine großartige Möglichkeit, Dinge zu tun. Wenn ich es jedoch auf einem statischen UITableViewController versuche, kann ich die Tabellenansicht nicht mehr scrollen. Irgendeine Idee warum?
Thomas Besnehard
2
Heutzutage ist es besser, es in einen Navigationscontroller einzubetten.
Malhal
Das ist eine gute Lösung, aber ein kleines Problem ist, dass beim Scrollen die Titel der Zellenkopfzeilen oben in der Navigationsleiste angezeigt werden.
Ali
Ich habe es gelöst, indem ich [self.view bringSubviewToFront:self.navigationBar];am Ende hinzugefügt habe -(void)layoutNavigationBar.
Ali
7

Ich möchte mitteilen, wie die akzeptierte Lösung in Projekten mit Storyboards verwendet werden kann:

Der einfache Ansatz besteht darin, vor dem VC einen leeren Storyboard-Navigationscontroller einzufügen, der modal dargestellt werden soll, sodass die Beziehungen wie folgt aussehen:

(Presenter VC) -> präsentiert modal -> (Navigationscontroller mit einem Controller, der als Root dargestellt werden soll).

Wir haben diesen Ansatz eine Weile ausprobiert und festgestellt, dass unsere Storyboards jeweils durch eine große Anzahl solcher Navigations-Zwischensteuerungen "verschmutzt" werden! von ihnen wird ausschließlich für einen verwendet! Präsentation eines anderen Controllers, den wir modal mit Navigationsleiste präsentieren möchten.

Unsere aktuelle Lösung besteht darin, den Code von der akzeptierten Antwort in einen benutzerdefinierten Abschnitt zu kapseln:

#import "ModalPresentationWithNavigationBarSegue.h"

@implementation ModalPresentationWithNavigationBarSegue

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

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

Mit diesem Abschnitt in unserem Projekt erstellen wir keine Navigations-Controller mehr in unseren Storyboards. Wir verwenden nur diese ModalPresentationWithNavigationBarSegue wie folgt:

Moderator VC -> Präsentierter VC

Ich hoffe, dass diese Antwort für Leute hilfreich ist, die unnötige Doppelarbeit in ihren Apps-Storyboards vermeiden möchten.

Stanislav Pankevich
quelle
5

Wenn Sie nur eine benötigen NavigationBar, können Sie eine Instanz von hinzufügen UINavigationBarund BarItems zuweisen.

xhan
quelle
Das hängt vom ViewController ab: Ich denke, Sie können einem UITableViewController keine UINavigationBar hinzufügen, oder?
Tobias
Gehen Sie in IB zu Editor -> In Navigation Controller einbetten, und Sie erhalten eine Navigationsleiste. Ziehen Sie BarButtonItems und fügen Sie sie hinzu.
AmitaiB
5

Ich wollte nur etwas zu dem hinzufügen, was @Scott gesagt hat. Seine Antwort ist definitiv die einfachste und am meisten akzeptierte Methode, dies jetzt mit Storyboards, iOS 7 und 8 zu tun ... (und bald auch mit 9).

Das Hinzufügen und Einbetten eines View Controllers zum Storyboard und das Einbetten wie von @Scott beschrieben ist der richtige Weg.

Fügen Sie dann einfach den Segue hinzu, indem Sie die Steuerung vom Quellansichts-Controller zum Ziel ziehen (das, das Sie modal anzeigen möchten), und wählen Sie "Modal präsentieren", wenn die kleine Ansicht mit den Auswahlmöglichkeiten für den Segue-Typ angezeigt wird. Wahrscheinlich auch gut, um ihm einen Namen zu geben (im folgenden Beispiel verwende ich "presentMyModalViewController").

Eine Sache, die ich brauchte, die fehlte, ist @ Scotts Fall, wenn Sie tatsächlich einige Daten an diesen modal dargestellten Ansichts-Controller weitergeben möchten, der in den Navigations-Controller eingebettet ist.

Wenn Sie den segue.destinationViewController greifen, handelt es sich um einen UINavigationController, nicht um den Controller, den Sie in den UINavigationController eingebettet haben.

Um zum eingebetteten Ansichts-Controller im Navigations-Controller zu gelangen, habe ich Folgendes getan:

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

Hoffe das hilft!

Evan Stone
quelle