Adding a subview to UINavigationController then back to the first subview? - iphone

I have a Navigation-Based app in which i added ABPeoplePickerNavigationController as a subview to my Navigation Contorller like this:
I have saved the view before adding subview into navView.
ABPeoplePickerNavigationController *peoplePicker = [[ABPeoplePickerNavigationController alloc] init];
peoplePicker.peoplePickerDelegate = self;
navView = [[UIView alloc] init];
navView = [[self.view superview] superview];
[[[self.view superview] superview] addSubview:[peoplePicker view]];
It works fine, but when I'm done with the PeoplePicker and I want to get back to the previous view. I used this code but it doesn't work.
[[[self.view superview] superview] addSubview:navView];
I don't get it, I have saved the navView from the subview, now I can't bring it back?

You need to add the back button, like so:
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];
Ideally your NavigationController is the root of your application, in which case any other view is a subview of it so you never trully swich away from your navigation controller, you merely change the actual view that is shown.
Also the way in which you attempt to reference your first view is fairly messy/confusing. You should change it to something like:
[appDelegate.navigationController topViewController];
or
[appDelegate.navigationController popToRootViewController];
I cant tell you for certain which to use as I am not sure of your exact view hierarchy, but I would highly recommend that you try to optimize that code.
I should probably note that the back button on the navigation controller and the the two lines below that do different things. The back button returns you one view back, while popToRoot and topView are both intended to bring you back to the very first viewController.
Edit: Changed the back button code to the code I actually use
Edit2: Just because I have a bit more space here I can try to understand your heirarchy better. It looks something like this?
Root View or Root View
-> Group View -> Group View
ABPeoplePicker View -> ABPeople Picker View
Root View
-> Group View
-> -> ABPeoplePicker
Meaning that ABPeoplePicker is nested within Group, and that is nested within your root? I think that its not working because what you actually have is one of the two on the first line, when what you want is the second line. Because I don't actually know which one you have without seeing it, I cant tell you exactly what to change, but if you want it to be nested all the way like the heirarchy on the second line, you need to push your group view onto the root view controller(Which is your navigation controller), then you want to push People Picker onto the root view controller again. After this your back button and view switching should be working the way you want it to.

Related

iPhone - Animating "back" to parent controller

I want to implement a "Next" feature in my app. The button appears on a ViewController that is shown by clicking on a row in a UITableView. Ideally what I would like is for Next to do the following (in pseudo code)
Go "back" to the UITableView
Scroll to next available item in UITableView
Select that item
I believe I can do 2,3 via selectRowAtIndexPath (please feel free to correct me if I am wrong) but I am unsure how to do Step 1. I will also have to target a method in the UITableView rather than the UIViewController that hosts the Button. How would I achieve this?
Update:
I can now target the rootViewController but now do I actually show it? (For reference here is my code, thanks to this question)
NSArray *viewControllers = self.navigationController.viewControllers;
UIViewController *rootViewController = [viewControllers objectAtIndex:viewControllers.count - 2];
UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithTitle:#"Next" style:UIBarButtonItemStyleDone target:rootViewController action:#selector(nextButton:)];
Update 2
I now have the back animation working but it keeps the navigation bar intact, how do I also set this back to the correct (rootViewController) one?
[self.navigationController popToRootViewControllerAnimated:YES];
If you have situation like this:
RootViewController - tableView
NextviewController - some view with Next button which shows after the you click on tableView
When you issue [self.navigationController popToRootViewControllerAnimated:YES]; from the 2. controller by pressing the Next button, it will bring RootViewController to the screen.
Now, on the RootViewController you have to "detect" back action (perhaps in ViewWillAppear) and continue with your steps 2. and 3.

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 do back animation when i go from current DetailView to previous DetailView?

I m making an app which has a main TableView. when we click any cell we got DetailView of that cell. we can also change DetailView without going back to main TableView by using next and prev button on every DetailView. When i click prev button. I get previous item'd DetailView but animation is like its going forward. i m using this:
[self.navigationController pushViewController:prevView animated:YES];
can anybody tell me how can i change that animation like Back button animation.
Thanx in advance
You have to store your navigationController, then 'pop' your current view with an animation and 'push' the detail view without an animation, for example like Squeegy did here. I've adjusted Squeegy's code a bit, the following should work:
// locally store the navigation controller since
// self.navigationController will be nil once we are popped
UINavigationController *navController = self.navigationController;
// retain ourselves so that the controller will still exist once it's popped off
[[self retain] autorelease];
// Pop this controller and replace with another
[navController popViewControllerAnimated:YES];
[navController pushViewController:prevView animated:NO];

Switching between 2 Views in 2 distinct View Controllers

I have a problem with transitioning between views in different ViewControllers.
Here is the situation:
My App is a TabBarApplication done with IB which contains a UIViewController for each Tab. The UIViewController (PlayerTabViewController) of the first tab contains another UIViewController (PlayerCreationViewController) to manage a view that will be added as subview.
I was able to add the subview using
[self.view addSubview:playerCreationViewController.view];
In the PlayerTabViewController.
The problem is that from the subview I have to return to the parent view and reload it because it contains a tableview that must be refreshed.
Using [self.view removeFromSuperview]; in the PlayerCreationViewController I can switch back to the parent view, but I'm not able to reload the tableview or do other actions.
I tried to implement the -(void)willRemoveSubview:(UIView *)subview method in PlayerTabViewController but it seems the function is never called.
Do you have an Idea of what am I doing wrong?
you are using wrong method to go on next view. just use navigation view controller to switch from one view to another view.
create a object of view
PlayerCreationViewController *playerViewController = [[PlayerCreationViewController alloc] initWithNibName:#"PlayerCreationViewController" bundle:nil];
[self.navigationController pushViewController:playerViewController animated:YES];
[playerViewController release];

iPhone SDK: Advancing from one view to another using a button tap

I want to make a really simple iphone app: one screen with a single button... when the button is tapped a new screen appears. That's it. No animations, nothing,
I've tried endlessly to make the NavBar sample project do this... and it works but only if I use a UINavigationController with a table that I can tap etc. I've tried all the skeleton projects in XCode too.
I thought I was done when I did this:
[[self navigationController] presentModalViewController:myViewController animated:YES];
But I couldn't do it without the UINavigationController. I just want a simple example.
Thanks so much!
One way you could do this is to create a new UIView and then when the button is pressed add that new UIVIew as a subview, therefore making it what you see.
If you make the new view its own subclass of UIView you would do something like this.
LoginView *login = [[LoginView alloc] initWithFrame: rect];
[mainView addSubview: login];
[self presentModalViewController:myViewController animated:NO];
Will pop up a new view, no animations, nothing. To get rid of it, inside myViewController:
[self dismissModalViewControllerAnimated:NO];
Though I reccomend you use the nice sliding animations (change NO to YES.) And yes, you can stack them up. I think this is better than creating a new UIView, but I may be wrong.
The correct way to do this is set up your project with a UINavigationController. In your root view controller, add your button in the view controllers's view. Then in viewDidLoad, register for UIControlEventTouchUpInside events from you button. Then, in your event callback, call:
[self.navigationController pushViewController:[[[SecondViewControllerClass alloc] initWithNib:nibName bundle:nil] autorelease]];
What kdbdallas suggested will work, but you won't get the nice sliding effects, nor will the navigation bar automatically change and provide your users with a back button.