I want to push root view controller. Why doesn't this code work?
RootController *rootController = [[RootController alloc]initWithStyle:UITableViewStylePlain];
[self.navigationController pushViewController:rootController animated:YES];
[rootController release];
I used addSubview like this before.
- (void)cancel {
[self.navigationController popViewControllerAnimated:YES];
}
- (void)viewDidLoad { // this is root view controller
[super viewDidLoad];
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancel)];
self.navigationItem.leftBarButtonItem = cancelButton;
[cancelButton release];
}
RootController *rootController = [[RootController alloc]initWithStyle:UITableViewStylePlain];
UINavigationController *aNavigationController = [[UINavigationController alloc]initWithRootViewController:rootController];
self.naviController = aNavigationController;
[aNavigationController release];
[rootController release];
[self.view addSubview:[naviController view]];
And I added cancel button in navigation bar to go back to previous view. It doesn't work.
So, I want to push instead of add.
You set the root controller in a UINavigationController using the
initWithRootViewController:
method. So, the way you are doing is correct. I would suggest you to inspect self.view and ensure that it is not nil.
EDIT: after your comment
You need to define a root view controller for your UINavigationController to work properly; from the UINavigationController reference:
Every navigation stack must have at least one view controller to act as the root.
So you cannot remove the root view controller. Possibly, to make things work as you like you should create an additional view controller to use as root view controller that you do not alter, then push your RootViewController on the navigation stack, then popping would work:
UIViewController *baseController = [[UIViewController alloc] initWithStyle:UITableViewStylePlain];
UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:baseController];
self.naviController = aNavigationController;
[aNavigationController release];
[baseController release];
[self.view addSubview:[naviController view]];
RootController *rootController = [[RootController alloc] initWithStyle:UITableViewStylePlain];
[self.navigationController pushViewController:rootController animated:YES];
[rootController release];
Notice that I first defined a simple UIViewController as root view controller, then pushed your controller on to it.
Once you do this, if you add the cancel button like you do, it will work popping the rootViewController from the navigation stack.
AFTER LAST COMMENT:
If I understand you right, when clicking on the cancel button, you want to get rid of the UINavigationController altogether.
In this case, use the following code for cancel:
- (void)cancel {
[self.navigationController.view removeFromSuperview];
}
If this guess is right, keep in mind that since you are not keeping any reference to the navigation controller, it will be deallocated and with it all the view controllers you instantiated.
If instead of removing the UINavigationController altogether, you would simpy hide the navigation bar, then after popping rootController, call:
setNavigationBarHidden:animated
Related
I have a UIViewController, I want to navigate from this view to my second view controller
SecondView *secondView=[[SecondView alloc] initWithNibName:#"SecondView" bundle:nil];
[self.navigationController pushViewController:secondView animated:YES];
[secondView release];
It doesn't work. It doesn't do anything and there is no error. What I'm missing?
SOLUTION
In Appdelegate file I've added a navigationcontroller.
UINavigationController *navCtrlr = [[UINavigationController alloc]initWithRootViewController:self.viewController];
[self.window setRootViewController:navCtrlr];
navCtrlr.delegate = self;
navCtrlr.navigationBarHidden = YES;
Is your view controller already inside a navigation controller otherwise it wont work. put an NSLog on self.navigationcontroller and see what it is printing
When I push cancel button in the third view, I want to go back to the first view directly.
I also want to remove the second view.
How can I do that?
This is the code.
// this part is in the first view.
self.second = [SecondController alloc] init];
[self.view addSubview:second.view];
// this part is in the second view.
ThirdController *thirdController = [[ThirdController alloc] initWithStyle:UITableViewStyleGrouped];
self.navigationController = [UINavigationController alloc] initWithRootViewController:thirdController];
[self.view addSubview:navigationController.view];
// this part is in the third view.
- (void)cancel {
[self.view removeFromSuperview]; // this only goes to the second view.
}
EDIT:
Can I use popToViewController in called contoller? My app crashes.
I thought popToViewController can be used only in calling controller.
And popToViewController is used when it was pushed.
I did add not push.
[self.navigationController popToViewController:[[self.navigationController viewControllers] objectAtIndex:0] animated:YES];
popToViewController:animated: is a UINavigationController method that you use when popping view controllers off the navigation controller stack. It doesn't fit for this scenario.
This user is adding subviews, not pushing them on a navigation controller stack.
As a note, it appears as a matter of design you should be using a navigation controller with the first view as the root controller, then the second pushed on the stack, and the third pushed on the stack. Then all you have to do is [self.navigationController popToRootViewControllerAnimated:YES].
I think this will work if you want to keep your current architecture:
// this part is in the third view.
- (void)cancel {
// remove the second view (self.view.superview) from the first view
[self.view.superview removeFromSuperView];
// can't recall, possibly you still need to remove the third view, but i think removing the superview will do it.
// [self.view removeFromSuperView];
}
If you prefer to try the UINavigationController route, then the easiest path is to create a new project in Xcode and select the type for a Navigation-Based Application or a Master-Detail Application. This will create a UINavigationController in a nib and add it to your window. You can then set the root view controller in Interface Builder to your FirstViewController class.
If you prefer to create the UINavigationController in code, then that is also possible. I show that below, along with the rest of the code you need, regardless of whether you create your UINavigationController in a nib in IB or in code.
I also recommend reading the View Controller Programming Guide for iOS.
In your app delegate or some other code:
-(void)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions [
// I would recommend setting up the UINavigationController and FirstViewController as IBOutlets in your nib, but it can be done in code.
FirstViewController* fvc = [[FirstViewController alloc] initWithNibName:#"FirstView" bundle:nil];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:fvc];
[window addSubView:navController.view];
[window makeKeyAndVisible];
[fvc release];
[navController release];
}
In the first view controller:
SecondViewController* svc = [[SecondViewController alloc] initWithNibName:#"SecondView" bundle:nil];
[self.navigationController pushViewController:svc animated:YES];
[svc release];
In the second view controller:
ThirdViewController* tvc = [[ThirdViewController alloc] initWithNibName:#"ThirdView" bundle:nil];
[self.navigationController pushViewController:tvc animated:YES];
[tvc release];
In the third view controller:
-(void)cancel {
// returns to the first view controller
[self.navigationController popToRootViewControllerAnimated:YES];
}
Use
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated
to go back to a specific view controller.
Try this:
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
This will pop to the view at index 1. Hope that Helps!
// this part is in the third view.
- (void)cancel {
self.first = [SecondController alloc] init];
[self.view addSubview:second.view];
}
And I think if you have you don't need to be worried about removing beneath view, later these will removed.
I'm extremly new to iphone and I have the following misunderstanding.
All over internet the tutorials about how to use NavigationController programatically it says:
NavigationController must be declared in applicationDidFinishLaunching and must be init with a root.After that you can add views to it.
I have this:
A UIViewController class meaning(AdiViewController.h, AdiViewController.m and AdiViewController.xib) and no Delegate file meaning no applicationDidFinishLaunching method.
What I wanna do is from my class-AdiViewController when pressing a button to go to another view.
I understand that I need a NavigationController which should retain my views having the root AdiViewController.
But my problem is where should I initializate that NavigationController in viewDidAppear??...cause I don't have the Delegate files.
If you could provide a minimal example with this small issue of mine it would be great.I'm sure that for those how are senior this is nothing but still I don't get it.Thanks
NavigationController must be declared in applicationDidFinishLaunching -> this is not true.
In your AdiViewController if you have button when you push that button you want to load navigation Controller right ?
// Hook this IBAction to your button in AdiViewController
- (IBAction)pushNavController
{
AnotherViewController* rootView = [[AnotherViewController alloc] initWithNibName:#"Anotherview" bundle:nil];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:rootView];
[rootView release];
[self presentModalViewController:navController animated:YES];
[navController release];
}
If you are in AnotherViewController i.e., you are in root view controller of Navigation controller. You need to push and pop view controllers from there. For example if you have a button in AnotherViewController:
// push next view controller onto navigation controller's stack
- (IBAction)pushNextViewController
{
NextViewController* nextView = [[NextViewController alloc] initWithNibName:#"NextView" bundle:nil];
[self.navigationController pushViewController:nextView animated:YES];
[nextView release];
}
// Similarly if you want to go back to AnotherViewController from NextViewController you just pop that from navigation controller's stack
- (IBAction)pushNextViewController
{
[self.navigationController popViewControllerAnimated:YES];
}
I have several views that I open one after another modally. View1 calls View2 and View2 calls View3.
I use this code to call the next view:
View2 *myView = [[View2 alloc] initWithNibName:#"View2" bundle:[NSBundle mainBundle]];
[self presentModalViewController:myView animated:YES];
[myView release];
If the user pushes cancel then it goes back one View… 3 to 2 and 2 to 1
[self.parentViewController dismissModalViewControllerAnimated:YES];
What I need to do is when the user is on View3 if they don’t select cancel but complete the operation, then I need to go back to View1 and release View2 and View3.
How do I do that?
EDIT: The MAIN WINDOW has a Navcontroller and 6 view controllers. I call the View 1 like this:
View1 *screen = [[View1 alloc] initWithNibName:#"View1" bundle:[NSBundle mainBundle]];
self.Search = screen;
[mainNavController presentModalViewController:screen animated:YES];
[screen release];
EDIT #2:
Main Windows calls View 1. Main Window has a NavController in the XIB this works:
View1 *screen = [[View1 alloc] initWithNibName:#"View1" bundle:[NSBundle mainBundle]];
[mainNavController presentModalViewController:screen animated:YES];
[screen release];
Then in the XIB on View 1 I added a NavController and tied it to View1NavController in the .h
View 1 then calls view 2:
View2 *myView = [[[View2 alloc] initWithNibName:#"View2" bundle:nil] autorelease];
UINavigationController * navController = [[[UINavigationController alloc] initWithRootViewController:myView] autorelease];
[View1NavController presentModalViewController:navController animated:YES];
When I execute this, no errors, but it doesnt show the View2.
Why don't you use UINavigationController? You can use both popToRootViewControllerAnimated: and popViewControllerAnimated: for your purpose.
As such if you do,
[self.parentViewController.parentViewController dismissModalViewControllerAnimated:YES];
You should go back to 1.
Excerpt from dismissModalViewControllerAnimated,
If you present several modal view controllers in succession, and thus build a stack of modal view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.
Using Navigation Controller
For navigation controller to work, instead of where your load your view1 you will do this,
View1 *myView = [[[View1 alloc] initWithNibName:#"View1" bundle:nil] autorelease];
UINavigationController * navController = [[[UINavigationController alloc] initWithRootViewController:myView] autorelease]
[mainNavController presentModalViewController:navController animated:YES];
This is assuming that view1 was the rootViewController
Once you've the navigation controller set up then you can load view2 like this,
View2 *myView = [[View2 alloc] initWithNibName:#"View2" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:myView animated:YES];
[myView release];
In such case,
Cancel
[self.navigationController popViewControllerAnimated:YES];
Complete
[self.navigationController popToRootViewControllerAnimated:YES];
Seems there is no smart way, try this stupid one:
UIViewController *vc = self;
while(vc.parentViewController.modalViewController == vc){
[[vc retain] autorelease];
[vc dismissModalViewControllerAnimated:NO];
vc = vc.parentViewController;
}
I have am setting up my application like so (in applicationDidFinishLaunching):
mytable = [[[MyTableController alloc] initWithStyle:UITableViewStylePlain] retain];
UINavigationController *mynav = [[[UINavigationController alloc]initWithRootViewController:mytable] autorelease];
[mynav.view setFrame:CGRectMake(0,0,320,460)];
UIViewController *tab1 = [[tabBarController viewControllers] objectAtIndex:0];
[mytable setTitle:#"Chronological"];
mytable.navigationController = mynav;
[tab1.view addSubview:mynav.view];
[window addSubview:tab1.view];
where MyTableController extends UITableController and has a navigation controller property. tabBarController is an outlet via the main nib file. There are no other nib files.
I am now unable to add any buttons to the navigation controller. Everything I do is ignored. What am I doing wrong here?
Can you include the code where you set up the UITabBarController tabBarController? I'm guessing that you are not properly setting the viewControllers property. Use UITabBarController -setViewControllers:animated: with an array of view controllers to initialize the tab bar controller.
Try something like this:
mytable = [[MyTableController alloc] initWithStyle:UITableViewStylePlain];
UINavigationController *mynav = [[UINavigationController alloc] initWithRootViewController:mytable];
[tabBarController setViewControllers:[NSArray arrayWithObject:mynav] animated:NO];
[mynav release];
[mytable release];
[tabBarController viewWillAppear:NO];
[window addSubview:[tabBarController view]];
[tabBarController viewDidAppear:NO];