Modal segue, navigation bar disappears
Asked Answered
P

11

54

I'm using Xcode 4.6.1 to code on Objective-C. I want to know how can I keep the navigation bar shown when I create a modal segue between 2 View controllers, because I'm doing the segue in the storyboard and when I run the application the navigation bar of the second view controller disappears, and I have a done button on that bar but I can't see it.

Polik answered 28/3, 2013 at 18:14 Comment(0)
D
64

Modal segues take over the whole screen, so any navigation bars, tool bars, or tab bars that are in the presenting controller will be covered up. If you want a navigation bar on this modal controller, you'll need to add one specifically to it, and add any buttons you want to that new navigation bar (or tool bar). If you don't want to do this, then don't present it modally, do a push to it.

Dedie answered 28/3, 2013 at 18:28 Comment(1)
Yes but in iOS 7 if you add a NavigationBar to the view in this way you don't get a single merged navigationBar and statusbar. Better to seque to a UINavigationController as detailed below.Weighin
H
90

Just add another Navigation Controller to your modal view controller. Follow the steps

  1. Select the Modal View Controller
  2. Go to Editor menu
  3. Select Embed In
  4. Select Navigation Controller

Run the application. Now it should work perfectly.

Hope this solves your problem.

Hoeg answered 20/6, 2013 at 5:21 Comment(5)
Thanks it really helps if you need to show some VC modally with NavigationBar and buttons (but do not want to see it in navigation stack with Back button). Just Embed your modal VC in Navigation and last one will hidden for usersHocus
Though don't like an idea of having redundant screen (Navigation Controller) just for showing some top toolbar.Gunner
See user3634990's answer below for details of how to reference the viewController (rootViewController) in prepareToSeque.Weighin
How can I remove this navigationController when going back?Incinerate
Can someone explain to me what is happening at a lower level? When we do a push segue to a VC that has a Nav Controller embed in it what does it mean?Emptyhanded
D
64

Modal segues take over the whole screen, so any navigation bars, tool bars, or tab bars that are in the presenting controller will be covered up. If you want a navigation bar on this modal controller, you'll need to add one specifically to it, and add any buttons you want to that new navigation bar (or tool bar). If you don't want to do this, then don't present it modally, do a push to it.

Dedie answered 28/3, 2013 at 18:28 Comment(1)
Yes but in iOS 7 if you add a NavigationBar to the view in this way you don't get a single merged navigationBar and statusbar. Better to seque to a UINavigationController as detailed below.Weighin
H
21

You could simply do the following to show the navigation bar:

Objective-C

UINavigationController alloc]initWithRootViewController:modalVC];

SWIFT 3

let modelVC = self.storyboard?.instantiateViewController(withIdentifier: "modalVC") as! ModalVC
let navBarOnModal: UINavigationController = UINavigationController(rootViewController: modalVC)
self.present(navBarOnModal, animated: true, completion: nil)

This will show the modal view controller with the navigation bar. Knowledge on Objective-C is limited, so I did not write the part of presenting. You should be able to figure that one out. ;)

Hope this helps!

Henrik answered 22/1, 2017 at 13:29 Comment(1)
This is great for when for some reason you don't want to change the structure of the storyboard (legacy code). It's kind of great anyway, actually. Tx!Wanitawanneeickel
S
10

In iOS 8 there is a better method. You can use adaptive presentation styles:

  1. Use a "Present as popover" segue
  2. Set your controller to adopt the UIPopoverPresentationControllerDelegate protocol
  3. Implement 2 methods

Objective-C:

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
    return UIModalPresentationFullScreen;
}

- (UIViewController *)presentationController:(UIPresentationController *)controller viewControllerForAdaptivePresentationStyle:(UIModalPresentationStyle)style {
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController: controller.presentedViewController];
    return navController;
}

Swift:

UIPopoverPresentationControllerDelegate
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
        return UIModalPresentationStyle.FullScreen
    }

func presentationController(controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
    var navController = UINavigationController(rootViewController: controller.presentedViewController)
    return navController
}

Swift 4:

extension MyViewController: UIPopoverPresentationControllerDelegate {
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
        return UIModalPresentationStyle.fullScreen
    }

    func presentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
        return UINavigationController(rootViewController: controller.presentedViewController)
    }
}

In prepare for segue method set the delegate:

   override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
        if let adpostVC = segue.destinationViewController as? XXXController {
            let popPC = adpostVC.popoverPresentationController
            popPC?.delegate = self
Straw answered 6/12, 2014 at 13:26 Comment(1)
I couldn't get this to work without assigning an anchor to the segue in Story Board (maybe this is an implied part of step #1?). But since I'm segueing from an Editing Menu option of a UITextView an anchor doesn't really make sense. Thoughts? Modal presentation seems like a better approach in at least some cases.Pigeonhole
I
6

swift version:

Follow steps:

  1. Embed VC in NavigationController
  2. Override prepareForSegue()

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
      if segue.identifier == "goToYourController" {
        let navigation: UINavigationController = segue.destinationViewController as! UINavigationController
    
        var vc = YourViewController.init()
        vc = navigation.viewControllers[0] as! YourViewController
        //if you need send something to destnation View Controller 
        //vc.delegate = self
      }
    }
    
Impermeable answered 13/5, 2016 at 12:23 Comment(0)
B
4

There is an easier way to do this. Like previous comments said (but didn't explain all the steps) you need to embed your desired destination view controller in a navigation controller, then set your destination view controller to be the Navigation Controller, then the Navigation controller calls the destination view controller.

First, embed the VC in a NavVC. Then you must write the code to set the segue destination to be the Nav VC.

The code looks like this:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    UINavigationController *nav = segue.destinationViewController;
    AddTriviaVC *triv = [[AddTriviaVC alloc]init];
    triv = nav.viewControllers[0]; 
    triv.location = self.location; 
} 

I hope this makes sense.

Bush answered 16/7, 2014 at 3:6 Comment(1)
Isn't the line AddTriviaVC *triv = [[AddTriviaVC alloc]init]; a dead store?Culhert
C
3

That is probably because you don't have a UINavigationController in your modal. You should use one (or just add a navigation bar to your ViewController in the Storyboard), and present that modally.

Caelum answered 28/3, 2013 at 18:28 Comment(0)
D
3

In order to show a navigation bar on a modal view controller, one way is to insert a navigation controller. You set the segue to this navigation controller as "Present Modally" and can set the presentation to "Full Screen" if needed.

Here's how it might look in Interface Builder, note that the "Title" and "Item" button will show now that we have inserted a navigation controller as the target of our segue.

enter image description here

Drolet answered 17/11, 2019 at 4:53 Comment(0)
P
1

You can add a toolbar programatically by doing the following in -(void)viewDidLoad

NSInteger tbHeight = 50;
tb = [[UIToolbar alloc] initWithFrame:CGRectMake(0, (self.view.frame.size.height - tbHeight), self.view.frame.size.width, tbHeight)];
tb.translucent = YES;
emailButton = [[UIBarButtonItem alloc] initWithTitle:@"Email Results" style:UIBarButtonItemStyleBordered target:tvController action:@selector(actionSheet:)];
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleBordered target:self action:@selector(doneButtonPressed:)];

NSArray *barButton  =   [[NSArray alloc] initWithObjects:emailButton,flexibleSpace,doneButton,nil];
[tb setItems:barButton];


[self.view addSubview:tb];

barButton = nil;

You will then have to create an IBAction for pressing the done button and it is done just like this:

-(IBAction)doneButtonPressed:(id)sender {
    [self dismissModalViewControllerAnimated:YES];
}

That should give you what you want with your modal view controller.

Paderewski answered 28/3, 2013 at 18:33 Comment(3)
Why was this minused? The code is correct for adding a toolbar to a modal view controller which is what the OP wanted. What am I missing here?Paderewski
I also don't understand how is this solution wrong? If someone who downvoted it would mind to explain...Embarrassment
the question was about a navigation bar (top bar with title) not a toolbar (bottom bar)Boresome
C
1

Here is my SHORTED version of "Volodymyr Nazarkevych" in Swift 4.2

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    super.prepare(for: segue, sender: sender)
    switch(segue.identifier ?? "") {

    case "segueIdentifier": // name of your segue
        let navigation: UINavigationController = segue.destination as! UINavigationController

        //here you create new name of your destination ViewController and assign his name to let constant above
        guard let myNewViewController = navigation.viewControllers[0] as? DestinationViewController
       //DestinationViewController is your 2-ViewController where you go to from first one.

       else {
            fatalError("Unexpected destination: \(segue.destination)")
        }
       // TO DO SOMETHING HERE

   default:
        fatalError("Unexpected Segue Identifier; \(String(describing: segue.identifier))")
    }
}

The code of "Volodymyr Nazarkevych" works perfectly, but only when your segue is from 1-ViewController to NavigationController of 2-ViewController, not directly to 2-ViewController. THANKS A LOT VOVA!.

Also in switch cases after destination block code you can do different stuff, for example to get some information or file from second ViewController.

Confutation answered 15/2, 2019 at 22:30 Comment(0)
M
0

in storyboard , you should add a Navigation Item to your new viewController, then add Bar Button Item for your done button

Magnanimity answered 6/1, 2018 at 6:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.