I am getting this error when I call my method dismissView. Here is the method stub:
-(IBAction)dismissView
{
RootViewController *rootController = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil];
[self.navigationController popToViewController:rootController animated:YES];
}
That should work, and I've checked, rootController is initialized and allocated. Any ideas?
I had this problem recently and solved with something like this...
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
The -popToViewController is used to pop view controllers OFF the stack, down to one that already exists. Your UINavigationController has a stack of ViewControllers (stored in the viewControllers property), when you popToViewController, you're going to want to pass one of the elements in that array as the first argument.
What you most likely want to do in this case is use -popViewControllerAnimated:, which will remove the top ViewController from the stack
Swift 4
For anyone still looking for a better solution that doesn't involve the UINavigationController stack indexes, which is getting more problematic with bigger navigation stack - here's the easiest way to solve this:
if let destinationViewController = navigationController?.viewControllers
.filter(
{$0 is DestinationViewController})
.first {
navigationController?.popToViewController(destinationViewController, animated: true)
}
You're allocating the RootViewController right there. It does not exist in the navigation controller's stack, so no matter how far you pop, you won't reach it.
If you are using Storyboads, use this segue:
#import "PopToControllerSegue.h"
#implementation PopToControllerSegue
- (void) perform
{
UIViewController *sourceViewController = (UIViewController *)self.sourceViewController;
UIViewController *destinationViewController = (UIViewController *)self.destinationViewController;
for (UIViewController* controller in sourceViewController.navigationController.viewControllers) {
if ([controller isKindOfClass:destinationViewController.class]) {
[sourceViewController.navigationController popToViewController:controller animated:YES];
return;
}
}
NSLog(#"PopToControllerSegue has failed!");
}
#end
When using Push Segues you can easily go back to the root using this method:
[self.navigationController popToRootViewControllerAnimated:YES];
When using Modal Segues (because of the word dismiss in the question and as a general reference) you can dismiss the view controller using this method:
[self dismissViewControllerAnimated:YES completion:nil];
The UINavigationController has a stack of ViewControllers which is stored in the viewControllers(NSArray) property. Enumerate to the required ViewController and pop to that ViewController.
Following code should solve the problem.
-(IBAction)dismissView
{
NSArray *array = self.navigationController.viewControllers;
for (id controller in array) {
if ([controller isKindOfClass:[RootViewController class]]) {
[self.navigationController popToViewController:controller animated:YES];
}
}
}
Try this one line solution.
Swift 4+:
self.navigationController?.popToViewController ((self.navigationController?.viewControllers[1]) as! Your_ViewController, animated: true)
Objective-C:
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
In my case the problem was that I was in the root ViewController and this works only for VCs that are stacked over it.
To pop to the RootViewController use
navigationController?.popToRootViewController(animated: true)
self.navigationController?.present(viewControllers, animated: true, completion: nil)
Related
The view controller may got by pushViewController or presentModalViewController from super view controller. In this view controller how should I know which way the controller from? I need it to close the view --
if (presentModalViewController ) {
[self dismissModalViewControllerAnimated:YES];
}else{
[self.navigationController popViewControllerAnimated:YES];
}
thanks
self.navigationController will be nil if the view is not in a nav controller (for example because it was presented). Of course if you present and have a nav controller, you'll need to dig deeper.
Additionally "self.presentingViewController" may be nil if you were not presented.
Note a common idiom for iOS is to create a simple protocol to handle closing the view. The view that pushes/presents is the delegate and gets their "viewWantsToClose" target called. If you create a new Utility project, you'll see what I'm talking about. This is how Apple flips the "info" view closed. You could potentially let your view accept a block for the "doCloseAction".
You are responsible for pushing or presenting a view so you should know when to pop or dismiss a view. If you still have to perform this kind of check, you can verify from the child view if self.navigationController is nil or not
You can do:
if (self.navigationController == nil) {
//[self dismissModalViewControllerAnimated:YES]; //Deprecated in iOS 6.0
[self dismissViewControllerAnimated:YES completion:nil];
}else{
[self.navigationController popViewControllerAnimated:YES];
}
or
NSArray* views = [self.navigationController viewControllers];
if (self.navigationController == nil || self == [views objectAtIndex:0])
{
//In the root view of navigationController or a presented View.
[self dismissViewControllerAnimated:YES completion:nil];
}else{
[self.navigationController popViewControllerAnimated:YES];
}
navigated from one view to another will and when i pop my view back viewWillAppear method is not calling.
can you please let me know the reason.
When you load View the first time viewWillAppear method is called? try to use
[[self navigationController] popViewControllerAnimated:TRUE];
to return back
It's typical that these problems are caused by improper use of view controller containment. You need to look at your view controller hierarchy and research the following methods:
[UIViewController addChildViewController:];
[UIViewController removeFromParentViewController:];
[UIViewController transitionFromViewController:toViewController:duration:options:animations:completion:]
[UIViewController willMoveToParentViewController:]
[UIViewController didMoveToParentViewController:]
Read the Implementing a Container View Controller section of the UIViewController Class Reference.
If u are doing all well than ur application is crashed some where, use break point and check , even you can check and follow these steps......
step 1. for push in FirstViewController
SecondViewController *second = [[SecondViewController alloc]init]
[self.navigationController pushViewController:second animated:TRUE];
Step 2. for pop in SecondViewController
//check navigation controller exist in ur application stack
NSArray *arrView = [self.navigationController viewControllers];
NSLog(#"arrView %#",arrView);
for(int i = 0; i <[arrView count]-1, i++)
{
if([arrView objectAtIndex:i] isKindOfClass:[FirstViewController class])
{
[self.navigationController popViewControllerAnimated:TRUE];
}
}
I've also met this situation.
In iOS 5, it's ok.
But when I test in iOS 4.3.1, viewWillAppear is not calling.
So you need call viewWillAppear manually
You can try this
[[self.navigationController.viewControllers objectAtIndex:0] viewWillAppear:YES];
[self.navigationController popViewControllerAnimated:YES];
I'm building an iPhone app, with the following structure:
I have the MainViewController which consists of 2 views (like split screen).
The first view of them, has a button. On tap, a UItableView (ResultTableViewController) appears in the second (of the above) view:
-(IBAction)buttonTapped:(id)sender {
if ([(UIButton *)sender tag] == 0) {
ResultsTableViewController *childViewController = [[ResultsTableViewController alloc] init];
childViewController.tableView.delegate = self.results;
[self.results.view addSubview:childViewController.tableView];
}
}
So I have a UItableView as a sub-view of a UIView.
The problem is that pushViewController() in didSelectRowAtIndexPath() of ResultTableViewController does not work (self.navigationController is nil).
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailsViewController *detailView = [[DetailsViewController alloc] initWithNibName:#"DetailsViewController" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:self.detailView animated:YES];
}
I have tried many of the solutions I found, but nothing works.
In my MainWindow.xib, I have only MainViewController added, is that the problem?
Thanks in advance!
You are adding the view of the child controller to your controller's view, not pushing the child controller onto your navigation stack. Due to that, your child controller's navigation controller will be nil, since it wasn't put into the navigation controller.
Is this what you're going for?
-(IBAction)buttonTapped:(id)sender {
if ([(UIButton *)sender tag] == 0) {
ResultsTableViewController *childViewController = [[ResultsTableViewController alloc] init];
childViewController.tableView.delegate = self.results;
[self.navigationController pushViewController:childViewController animated:YES];
}
}
[self.navigationController pushViewController:self.detailView animated:YES];
above line of code will push the detailview on navigationcontroller stack. Check whethere your tableviewcontroller is on that stack ?
Ok, I found it.
I had to declare my MainViewController as UINavigationControllerDelegate and create a secondary NavigationController in it. I push the viewController in my new navigationController and that's it.
I am completely new to iPhone development. I have two ViewControllers
ViewControllerA
ViewControllerB
ViewControllerA is the first one and launches with the app.
I have another ViewControllerB now I want to add view of ViewControllerB as subview to ViewControllerA's view when application launches.
Try this
ViewControllerB *vcb = [[ViewControllerB alloc] init];
[self.view addSubview:vcb.view];
A belated answer. I just wrote some words about my solution for this question. It can be found here:
http://blog.nguyenthanhnhon.info/2014/04/how-to-add-viewcontrollernavigationcont.html
You need to declare the object of VC globally .. otherwise you face some issues.
#interface ViewControllerA ()
{
ViewControllerB *viewControllerBObj;
}
-(void) viewDidLoad
{
[super viewDidLoad];
viewControllerBObj = [[ViewControllerB alloc]initWithNibName:#"ViewControllerB" bundle:nil];
[self.view addSubview:viewControllerBObj.view];
}
try this
in "viewDidLoad" method of "ViewController1"
ViewController2 *vc2 = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController2"];
[self addChildViewController: vc2];
[self.view addSubview: vc2.view];
You can access the view of a view controller by using it's view property. If you have pointers to two view controllers myControllerA and myControllerB then you can add B's view to A's view by using this.
[myControllerA.view addSubview:myControllerB.view];
Add [self.view addSubView:ViewControllerB.view] in the viewDidLoad() of ViewControllerA.
here's my code:
ViewController *vc = [[ViewController alloc] initWithNibName:#"TableView" bundle:nil];
[self.navigationController presentModalViewController:vc animated:YES];
//[self setView:[vc view]];
If I call it, nothing happens. However, if I change it to:
ViewController *vc = [[ViewController alloc] initWithNibName:#"TableView" bundle:nil];
//[self.navigationController presentModalViewController:vc animated:YES];
[self setView:[vc view]];
The view appears just fine (without the transition, of course).
What am I doing wrong? Is there anything special you have to take care of when initializing the view controller? I tried to copy as much as possible from Apple's examples, but I can't get this to work...
Thanks for any input!
-- Ry
You can only present modal view controllers from controllers that have already been shown onscreen (usually through a UINavigationController or UITabBarController). Try creating a UINavigationController, pushing a viewController to it, and then presenting your modal controller. There's a starter project in Xcode that shows how to create a UINavigationController-based flow if you're unfamiliar with it.
One other thing to note: if you haven't pushed the view controller onto a UINavigationController, the .navigationController property will be nil, and messaging it will have no effect.
I encountered the same problem while attempting to show a modal view over another modal view. Ben's answer is correct, and can be implemented like so:
#interface FirstView: UIViewController {
UIViewController *firstView;
}
- (IBAction)showOptionsView:(id)sender;
#end
In the main view class:
- (void)viewDidLoad {
[super viewDidLoad];
firstView = [[UIViewController alloc]init];
[firstView setView:self.view];
[firstView setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
}
- (IBAction)showOptionsView:(id)sender {
OptionsView *optView = [[OptionsView alloc]initWithNibName:#"OptionsView" bundle:nil];
if(firstView != nil) {
[firstView presentModalViewController:optView animated:YES];
[optView release];
}