Pushing a navigation controller is not supported- performing segues - objective-c

I created a new navigation controller in my storyboard (not programmatically!) and set it to be "Root View Controller" to a regular UIViewController and added a button in it which says- forward to the next view controller (this second view controller is a view controller which I want that will have a back button to link to the initial view controller).
Now, whenever I try to link the button to the next view controller- "Pushing a navigation controller is not supported".
Help me please, and thanks
EDIT:
I accidentally subclassed UINavigationController, and not UIViewController in my class.
Thank you anyway.

I've tried this and have no problems, its all done in IB with no additional code required ...
Start a new project, "Single View Application" using story boards
Select storyboard and delete the views its produced.
Drag on a new Navigation Controller (it will bring a table view with it)
Delete the table and the table view controller, so you are just left with the Navigation Controller
Drag on a normal view controller
Right Click and drag from the Navigation controller to the new View and choose "Relationship - Root View Controller"
Drag a "Bar Button Item" on to the Navbar which should be visible on the top of your ViewController, you can rename this Forward if you wish.
Now drag on another view controller which is the one your "Forward" button will push in to view.
Right Click and drag from the bar button to the 2nd View Controller, and choose "Push"
Run the project and you will get a Single view with a Navbar and your button, clicking your button will Push the other view and give you a Back Button to return to the first View Controller. I'll try and post a picture of my storyboard if it helps.
Plasma

I had the same trouble. I wanted to have a navigation controller on each storyboard, so that each could run independently, be individually debugged, and so that the look would be right with the navigation bar.
Using other approaches, I found the UINavigationController would be retained from the original storyboard -- which I didn't want -- or I'd get errors.
Using the AppDelegate in your view controller to set the rootViewController worked for me (borrowing segue naming conventions from Segue to another storyboard?):
- (void)showStartupNavigationController {
NSLog(#"-- Loading storyboard --");
//Get the storyboard from the main bundle.
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Startup" bundle:nil];
//The navigation controller, not the view controller, is marked as the initial scene.
UINavigationController *theInitialViewController = [storyBoard instantiateInitialViewController];
NSLog(#"-- Loading storyboard -- Nav controller: %#", theInitialViewController);
//Remove the current navigation controller.
[self.navigationController.view removeFromSuperview];
UIWindow *window = [(AppDelegate *)[[UIApplication sharedApplication] delegate] window];
window.rootViewController = theInitialViewController;

To swap views Programatically you would need to select the segue and give it an Identifier like "PushView" then call it like this ....
[self performSegueWithIdentifier:#"PushView" sender:self];
That will programatically do the same as clicking the forward button. I've created you an example project with the code discussed above. Has an -(IBAction) with code in you can use for programatially changing the view.
PushView.zip

I also wanted to do this, present a screen (that had an embedded navigation controller) when the user pushes a button.
At my first attempt, I connected the segue from the button in the fist screen to the Navigation Controller, and the app was crashing with this error "Pushing a navigation controller is not supported".
This is the solution I found:
Select the segue from the button in the first screen to the navigation controller.
If it had an identifier, copy its name. Then delete that segue.
Then create a new segue by CTRL-clicking the button in the first view controller and dragging to the VIEW CONTROLLER YOU WANT TO PRESENT (not to the Navigation Controller that is pointing at it), and select Push in the small pop up window.
Then click the icon in the middle of the segue and paste the name you copied in the first step as an identifier for it.
IB is going to give you a warning "Scene is unreachable due to lack of entry points and does not have an identifier for runtime access via -instantiateViewControllerWithIdentifier:." Don't worry, it works perfectly.
If you want to customize the string that is shown as the Back button to return, you can add this line in the viewDidLoad method OF THE VIEW CONTROLLER THAT IS BEING SHOWED AFTER THE BUTTON IS PRESSED, that is the Child view controller.
(replace "Settings" with the name you need)
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBar.topItem.title = #"Settings";
...
}

Related

Why UINavigationController keep popping out the top controller

I have UITabBarController, one of the tab points to a UINavigationController. The UINavigationController rootViewController is of class BGProfileView which shows users' profile
At viewDidAppear, I arranged that if users didn't logged in it will push a BGLogin view controller.
[BGLogin alreadyLoggedin:self.navigationController hideBackButton:YES anddoBlock:^{
[self whatToDoAfterLogin];
}];
Now everything is fine but with one minor issue. If I press the tab again, BGLogin will be poped out of UINavigationController.
I have no idea what makes that BGLogin poped out.
If I select a different tab and then click back to the BGProfile tab, this doesn't happen. It just happens when I click the same active tab. So I am in BGProfile tab, and I click that tab again. Basically it happens when I select the active tab that should simply do nothing. In fact, it does do nothing on others.
I put a breakpoint in viewWillDisappear and this is what I see:
As you see, viewDidAppear is called by the main loop. But why the hell the mainloop call viewDidAppear? Usually there is a code saying things like nav popViewController
Chances are there . that your tab bar controller is pushing new navigation controller with root view controller. and you interpreting that it's popping out. When same tab is selected you need to tell your tabBarController to not to do anything explicitly.
Example
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
UIViewController *tbSelectedController = self.tabBarController.selectedViewController;
if ([tbSelectedController isEqual:viewController]) {
return NO;
}
return YES;
}

How to TabBarController display differents Items?

On my firstViewController I have a tabbar that contains my firstViewController and a helpViewController.
When I click on a button from the FirstViewController, I push a NewViewController. But, when this view is pushed, I want to change the content from the TabBarController to display other ViewControllers, like infoViewController, optionViewController and NewViewController. Is that possible?
The First Image represents my application. The FirstViewController has a button that will push the NewViewController. When the user clicks this button, I want that my app shows what is in the second image. Is possible?
Yes, this is possible (I just did a proof of concept in Xcode). Assuming that you are using storyboarding, you need to make your initial view controller a UINavigationController otherwise you won't be able to use the push segues. Then, make the first UITabBarViewController the root view controller of the navigation controller. Put an entirely new UITabBarController into the storyboard, and then put a UIButton into the firstViewController and link it via a push segue to the new (second) UITabBarController.
When you tap the button the old tab bar will slide off, and the new one will slide on.
Here's an example of how it all looks:
!!This app uses navigationController and TabBarController!!
Using the storyboard I saw each piece of the app, then I had the Idea: Insted of pushing the NewViewController, how about push a tabBarController? When the user clicks the button, the app will push the tabBarController with 2 TabController`s.
Just add New File to your project, sub classed UITabBarController. Then add this code to the init method of your tabBarController: self.hidesBottonBarWhenPushed = YES;
On ViewDidLoad just alloc and init what views you want to display on the tabBar and
self setViewControllers:[NSArray arrayWithObjects: vc1, vc2, vc3, nil]];
Working fine here :D
You can nest TabBarControllers. But that would look strange. And the first TabBar wouldn't be changed. Pushing a TabBarController into a TabBarController is not possible because TabBarController does not support pushViewController. Thats only possible with a NavigationController.
Anyhow you can change the content of the TabBar completely programatically.

Modal UIViewController will not push to next UIViewController

The start of the structure is as follows...
UITabBarController -> UINavigationController(s)
From each of the UINavigationControllers, I have a UIBarButtonItem that modally presents a UIViewController.
This UIViewController has a MKMapView with pins at multiple locations. When clicked, they display an annotation with a disclosure button.
Within this UIViewController, it is my intention to push a detail page (UITableViewController) when pressing the disclosure button of the annotation. The method calloutAccessoryControlTapped: receives the appropriate pin, but the transition to the next controller fails.
I have tried every combination of the following methods...
[self.navigationController ...]
[self.parentViewController ...]
[self.parentViewController.navigationController ...]
with the method being either...
presentModalViewController:
pushViewController:
I have done all of these with the UIViewController being on its own, and also with it embedded inside of a UINavigationController.
All of these properties return null...
self.navigationController
self.parentViewController
self.parentViewController.navigationController
This is the first time I've used storyboard for an Xcode project. Am I missing a step?
Try getting rid of the code and implementing the transitions in storyboard by control dragging from the button to the view controller you wish to load modally. When the "Storyboard Segue" menu pops up select "modal". In the modal view controller, I like to use code to return from the modal by calling:
[self dismissModalViewControllerAnimated:YES];
To Presenting Storyboard View Controllers Programmatically scroll to that section in gravityjack on the link provided.
For example, I have a view controller that I created in storyboard which I can call programmatically with the following two statements:
SettingsViewController *settingsVC = [self.storyboard instantiateViewControllerWithIdentifier:#"settingsVC"];
[self.navigationController pushViewController:settingsVC animated:YES];

Add new TableView to another UINavigationController

My app setup is the following
With this setup, when I press the button in table 2 it pushes the view (table3) in the "nav 2" hierarchy.
What I need to do is to press the button on table 2 and push the view (table3) but in the hierarchy of the "nav 1". And if I press the "back" button in table 3, I want to go to the "Table 1", and NOT being able to return to the table2 view.
I need to do this programmatically. Im a beginner in iOS development, and I know I should modify use the method:
[self.navigationController pushViewController:..........];
But the problem is that in this way I am pushing it to the navigation controller of "self" meaning nav2. How do I push it to nav1?
NOTE: The layout I need is similar to the one found in "Messages" app when adding a new message thread.
Thank you!
If you are trying to model the Messages app of navigation, you need to present a modal view controller with a navigation controller.
NewViewController *newVC = [[NewViewController alloc] initWithNibName:#"NewViewController" bundle:nil];
UINavigationController *newNav = [[UINavigationController alloc] initWithRootViewController:newVC];
[newVC release];
[self.navigationController presentModalViewController:newNav animated:YES];
In the message app, it looks like they are presented in a modal view. Then if you press the + button to get to the contacts it brings up another modal view wrapped in a NavigationController. If your using X-ode 4.2 and create a new ViewController in the storyboard there an option in the editor menu to embed that view in a NavigationController. then just present that view modally.

Adding Navigation from home page

I'm adding navigation to subviews in my app from the home view.
I understand the concepts of pushing and popping view in the navigation stack, however, I don't want the navigation bar in the home screen.
Basically, when the user leaves the home view to any sub view, I'd like them to see the "Home" button on the left of the button nav bar, but no nav bar in the home view.
Any help would be appreciated.
It sounds like you want to start out with a bare UIViewController, containing your home screen with your own custom buttons.
The UINavigationController should come into play only when a user performs some action. Do this by
[navVC setModalTransitionStyle:UIModalTransitionStyleCrossDissolve]; // pick an effect
[self.viewController presentModalViewController:VC animated:YES];
Where navVC is the navigation controller, and self.viewController refers to your (new) main view controller. (add a suitable line IBOutlet UIViewController *viewController; + #property line + #synthesize line)
You need to fiddle a bit in the way the app starts up, for now it will probably show the navigation controller directly. If you are using a xib, you can do this by adding a UIViewController while leaving the navigation controller there as it stands. In application: didFinishLaunchingWithOptions: you'll find a line saying
[window addSubview:...];
which actually determines which viewcontroller's view is first visible. Change this to:
[window addSubview:self.viewController.view];
If you've done all this correctly, you've inserted the extra UIViewController between startup and navigation.