What happens to unused views in UINavigation controller? - iphone

I am implementing a shopping cart in iOS.
I am using a UINavigationController to show UIViewControllers for each step of the process. Users can use the back button and change things.
But after they submit the order I don’t want them to go back. What is the correct way to show a view without the back button using the navigation controller?
When you do that, what happen to the previous UIViewControllers? Are they deallocated ? Obviously I don’t need them. Do I have to manually deallocate them?

You have to deallocate those view controllers. They will start to leak, otherwise. I guess, you would be pushing the view controllers somehow similar to the following.
MyViewController *myViewController = [[MyViewController alloc] init];
[self.navigationController pushViewController:myViewController animated:YES];
[myViewController release];
If you are doing like this, you have no need to worry about those view controllers, later. They will be released by the UINavigationController when it is done them.
Hiding the back button: Add the following line in the loadView method of your last view controller.
[self.navigationItem setHidesBackButton:YES];

You can tell it to go to a specific view controller either with something like:
[myNavController popToRootViewControllerAnimated:YES];
Or, there's also a UINavigationController method to give it an array of view controllers, it should present the first one.

Related

How to use UItableView and UINavigationController in a "search" application ? Best practices

I would like to combine UITableView and UINaviationController in an app but as a newbie most apps I've seen just send you straight to the results view (UITableView). But, I guess a "normal" search application does not assume you have the results on the first screen. There should be a search form on first screen with input fields and a button that triggers the search process and show some results and navigation.
So, I'm just trying to replicate this normal behaviour in my app. I've already made the search form (no navigation shown on it, of course) and a seperated View called "ListingViewController" with its related View and containing a UITableView and where I think I should add the Navigation...The next idea will be to make a DetailViewController and possibly and ListingMapController to show the listing in a GoogleMap.
So, where I'm stuck at is how to add this Navigation Controller ?
Some suggested me to add it in the SearchViewController delegate...
But I don't want a navigation on search form of course...
Some suggested me to open the Navigation controller modally...
But, I"m also planning at adding a Tab Bar to allow user to see other informations (like About,etc...) and with a modal Nav controller I don't know if they will still see the bottom Tabbar...
Any suggestions? What do you think is of best practices especially to avoid my app of being rejected by Apple?
Thx in advance for reading and helping!
Stephane
You could init the navigationController with your View Controller as the root view Controller. Then hide the navigationBar (if you need to). You would then add the navigationController.view as the subview. This will basically look like the original view controller. Then you can pushViewController: animated: to push the results view Controller.
So, for example in your AppDelegate (or in the proper view controller):
Create a property and ivar for a UINavigationController and hook up its outlets in interface builder. Then set your search controller as the root view controller for the nav bar, and add it as a subview.
MySearchViewController* searchController = [[MySearchViewController alloc] init];
self.myNavigationController = [[UINavigationController alloc] initWithRootController:searchController];
[searchController release];
self.myNavigationController.navigationBarHidden = YES;
[self.window addSubview:self.myNavigationController.view];
[self.window makeKeyAndVisible];
Then of course in your searchController, you would simply say:
ResultsViewController* myResultsViewController = [[MyResultsViewController alloc] init];
//You may want to create another init method and pass in some arguments like an array:
// [[MyResultsViewController alloc] initWithResults:results];
then push the viewController
//This is in your search controller class
[self.navigationController pushViewController:myResultsViewController Animated:YES];
[myResultsViewController release];
from the results viewController, to get back you pop the view controller off of the navigationController view controller's stack.
//In results view controller perhaps in some IBAction for a back button:
-(IBAction)backButtonPressed:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}

iOS: confused about removeFromSuperview and switching views

New to iPhone development, but I've been given a big project as a first go and I'm a bit stuck.
Basically the app will start with a settings screen, then you click a button to go to a dashboard with multiple option buttons. Each button will lead to a different Navigation View with tables.
The way I've approached this is to start with a UIViewController with a button, which I've got wired up but when you hit the button and I do:
[self.view removeFromSuperview];
UIViewController *newView = [[UIViewController alloc] initWithNibName:#"Dashboard" bundle:nil];
[self.view addSubview:newView.view];
the second view isn't loading. I just get a blank screen. Do I need to make a reference in the first controller to the second?
Also, am I approaching this in the right way? As long as I removeFromSuperview will I be able to load the navigation controllers on the press of a button?
Sorry if this isn't too clear, I've been through books and lots of websites but don't seem to be able to get my head around this.
Thanks
There is nothing here with the new view, rather the problem is with current view. You have removed the self.view from super view.
[self.view removeFromSuperview];
So anything added to self.view will not be shown, as self.view itself is removed.
When presenting child controller/view from a parent controller, you should consider using presentViewController. Eventually, use dismissViewControllerAnimated when you want child to disappear and parent to reappear.
In parent view controller:
ChildViewController * child = [[ChildViewController alloc] init];
[self presentViewController:child animation:YES completion:Nil];
In child view controller, ie. in some action handler:
-(IBAction)close:(id)sender
{
[self dismissViewControllerAnimated:YES completion:Nil];
}
IMHO you should also get in the habit of naming instance variables to what they are instantiated from. In your example you name the instance newView, when it should be something like newViewController. That way you make sure you don't mix up views with view controllers.
[self.view removeFromSuperview];
You've removed the view from the superview
[self.view addSubview:newView.view];
But you're adding the new view to the same view that you have just removed from the superview. It's not displaying anywhere.
Your third line adds newView as a subview of self.view, but you just removed self.view from it's superview.
I'd suggest reading more about view controllers. You'll want to have one view controller per "screen", so one for your settings screen, one for your dashboard, one for each table, and so on. Then, manage which one is visible by pushing and popping these view controllers from the nav controller's stack.
This removes self.view, which will most likely destroy the object since there will be no other references to it:
[self.view removeFromSuperview];
Here you are creating an UIViewController, and adding it's view to self.view, which is probably not what you want:
UIViewController *newView = [[UIViewController alloc] initWithNibName:#"Dashboard" bundle:nil];
[self.view addSubview:newView.view];
Look into UINavigationController so that you can easily swap screens in and out with some built in animations. Here's a bit more about them. Here's a tutorial.
The UIViewController's view should not be removed from or added to a view hierarchy outside the control of the view controller. While you might be able to get that manipulation to work now it won't in the future.
Read up on view controllers here.
The basic idea is that you present the view controller then it will take care of manipulating the view hierarchy for you.
So a better approach to get started would be to do something like this;
[viewController1 presentModalViewController:viewController2 animated:YES];
This line of code will present viewController2 with the default modal animation (slide in from the bottom). If you'd like a different animation you can change the modalPresentationStyle to one of the constants in the UIModalPresentationStyle enum on viewController1 (note thats a viewController1, not viewController2).
If you want something more like the Clock app look into the tab bar controller. If you want something more like the Mail app look into the navigation controller.

how to pop a controller off the navigation stack without using the navigation bar

I'm trying to implement a navigation controller with some hierarchical views. I want to use a regular UIViewController to present choices for drilling down, I don't want to use the navigation bar - I want to have my own, custom buttons for returning back up a level.
I see examples like:
[[self navigationController] pushViewController:nextViewController animated:YES];
and my questions are these: Is navigationController a property of all UIViewControllers? Can I refer to self.navigationController regardless of the view that's on the stack? If I'm at an arbitrary view, can I have a button action that contains something like [self.navigationController popToRootViewController animated:YES];
Each view I present will need a button to return to the previous view, or to the root view, depending on the situation. I want to create that button in each view controller and control which view in the stack it returns to. Am I on the right track?
Is navigationController a property of all UIViewControllers?
Yes.
Can I refer to self.navigationController regardless of the view that's on the stack?
Every UIViewController on the UINavigationController's stack will return the UINavigationController object when calling navigationController on it.
If I'm at an arbitrary view, can I have a button action that contains something like [self.navigationController popToRootViewControllerAnimated:YES];
Yes. popToRootViewControllerAnimated: will take the user to the root UIViewController for the UINavigationController, and you can use [self.navigationController popViewControllerAnimated:YES]; to just pop off the top UIViewController. This last one does the same as tapping the Back UIBarButtonItem.
Am I on the right track?
Yes :)

iPhone: Push Navigation Controller (w/ TableViewController) onto stack. Is this possible?

I have a view which contains a UIButton. When this is clicked, it calls a method that loads another NIB. Now, normally, that nib would load a view onto the stack, and everything would be fine. But, I am trying to load a Navigation Controller (so that I can have table views that are multiple levels deep), and all I get it errors.
What is the proper method for loading a Navigation Controller and putting it on the top of the stack?
As the other poster said you should create your Nav controller in your AppDelegate. If you are adding a new UIView to the stack like presentModalViewController you want to create the UIView then add the Nav Controller to it. If you don't want nav controller on that screen but the next just use the navController.hidden property I think it is.
To add the nav controller to the view do this:
NoticesView *noticesScreen = [[[NoticesView alloc] init] autorelease];
noticesScreen.delegate = self;
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:notices_screen] autorelease];
[self presentModalViewController:navController animated:YES];
Hope that helps towards your question. Still trying to find out exactly what your doing
Create the navigation controller in the app delegate. Push your mapview onto the stack as the first view. Push your tableview onto the stack as the second. If you started with a view-based app template, you won't have a navigationcontroller instantiated at all. (Been there done that) the easiest way out of this is to use xCode to make a navigation based applcation and then copy the code out of that. If you do already have a navigation controller, then just push the view controllers as above.

How to remove all the view along with rootView from UINavigationController in iPhone

I have an UIView added in the main window with a controller. On clik of a button on this view I want to load a UINavigationController which will migrate to multiple views pushing them one by one on stack. Now what I want to do is when user reaches at the end of views, in the last view I have a done button. ON clik of this button I want to move back to my first screen unloading the NavigationController from the memory.
What is the best way to do it since popToRootViewController takes you to the first screen of UINavigationController which is my second screen.
You basically want to remove the navigation controllers view, so why cant you just say [navigationController.view removeFromSuperView] ?
One way to do this is to present the navigation controller as a modal view controller, and dismiss it when you're done:
// In the parent controller, when the navigation controller is about to appear:
UINavigationController* navController = [[UINavigationController alloc] init];
[self presentModalViewController:navController animated:YES];
// ... later, in the nav controller, when it's done being used:
[self.parentViewController dismissModalViewControllerAnimated:YES];
[self autorelease]; // goodbye, cruel world (when the ar pool is drained)
A few ideas, in order of desirability
make Controller #1 the root view controller of the stack and then use popToRootViewController. Is there a good reason why you aren't doing this already? Keep in mind you can easily hide the navigation bar from any controller, if that's what you're afraid of.
Add a method called "destroyNavigationStack" or something to main Controller #1 and have a reference to controller #1 in your app delegate. In your Nth view controller, when "done" is hit, get a reference to your app delegate (UIApplication's sharedApplication method), and send View Controller #1 this "destroy" message. There really is no reason to even think about popping view controllers off of the stack since you just want to get rid of the entire stack anyway.
Make ViewController #1 a singleton and call destroyNavigationStack