I don't want to let the navigation controller show its navigation bar in the whole project.
Now there are three view controllers
(1) Login view controller
(2) Sign up view controller
(3) Home view controller.
I just hope to use action(which can be triggered by any kind of event, i.e. drag gesture, not necessary the pressing button) to switch between these view controllers. But I found once I get to the "signup view controllers", I can not go back to the login view controller, since there is no "BACK" navigation bar.
Questions:
How "PUSH" in one view controller, then "POP" in the other view controller?
Or there is some different way to solve this problem?
Thank you so much, any suggestion is great.
To programmaticaly go backward in a navigation controller's navigation stack, call this method:
[self popViewControllerAnimated:YES];
When and where you call this is up to how you want your app to flow. Essentially, the default navigation controller calls this automatically when the navbar's back button is pressed. But if you hide the navbar and still need to pop back, you can call this method to pop back.
As for pushing forward, it's simply a matter of creating a Push segue on the storyboard, giving it a name, and then in your code, call this method:
[self performSegueWithIdentifier:#"segue_YOUR_SEGUE_ID" sender:self];
On the question of your app, what probably makes most sense is for the login view be a view by itself. It should contain a modal segue to a sign up view for new users as well as a modal segue to the home view controller (which may or may not need to be embedded in a navigation controller).
Performing a modal segue works exactly the same as a push segue (if you're using storyboards. Hook up the segue, choose a modal segue, then call the performSegueWithIdentifier: method in your code when you need the segue to occur.
Dismissing a modal view is slightly different, but still quite simple. It goes like this:
[self dismissViewControllerAnimated:YES completion:nil];
It's fairly check to do with an 'if' statement...
if (self.navigationController.navigationBarHidden == NO) {
//YOUR ACTION
}
Hope that helps!
Related
I'm trying to create an app using storyboard which has 4 scenes:
ChooseLoginMethod
EnterLoginData
SuccessfulLogin
MainScene.
What I'm doing right now is the following: I have an UINavigationController which has ChooseLoginMethod as its root view. ChooseLoginMethod has several buttons (for different login methods) which are push segues to EnterLoginData. EnterLoginData has a push segue to SuccesfullLogin and SucessfullLogin has a push segue to MainScene.
The problem is that SuccessfulLogin and MainScene display the back button on the top bar, which makes no sense for the application.
I've tried:
Hidding the top bar on these two Views. Not successful.
Changing the segue to modal. Seems to work, but doesn't feel like the right thing to do.
So what I would like to do is create a segue which breaks the chain of Views which are on the UINavigationController's stack. Is there a proper way to do this in storyboard?
-- edit --
Maybe what I should do is replace the root view ( Set root view for UINavigationController ). This may work, but seems like a programming work-around for something that should be possible to be done in storyboard. Or maybe it is just me not getting the "iOS way of doing stuff".
You had to use setNavigationBarHidden before the viewcontroller appears on the screen, like in viewWillAppear.
But then you can't go back from "MainScene" to the "RootController". So you should do something like popToRootViewController after "SuccessfulLogin" and then pop "MainScene".
I think it's usually best to have your main scene be the root view controller. From its viewDidAppear method, you can present your ChooseLoginMethod controller modally, and from there do modal transitions to your other login controllers. When you get to the end, and you want to go back to the main scene just dismiss the modals from the root view controller -- this will dismiss the first one, and any that were presented from it:
[self.view.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
This is my Hierarchy
Navigation Controller --> Login Controller View --- > Register Controller View
--> My Small Internal LeaderBoard View
Now I am using segues (Push) to go to either LoginControllerView or LeaderBoardView
Once I am on LoginControllerView and then RegisterControllerView I am using this code
[self dismissViewControllerAnimated:YES completion:nil]
However instead of returning me to LoginControllerView it is returning me back to NavigationController.
How can I return to my LoginController
I am transitioning from Login to Register through PUSH segue and I have named the segue as "Register"
From Login To RegisterController I am using this code
[self PerformSegueWithIdentifier:#"Register" sender:Self]
However, I can see from RegisterView connection inspector that its viewController reference StoryBoard Segue is "Login" .. I am transitioning from Login to Register with Register Segue, How can my RegisterController has Login segue as reference?
You did not say how RegisterControllerView is being presented. If it is being pushed on the navigation controller stack, then why not call:
[self.navigationController popViewControllerAnimated:YES];
If you are doing something special, then you need to say what special thing you are doing.
Also, note that if you find where a view controller is trying to dismiss itself, then you should at minimum revisit your design to see if that's really the best thing to do. A view controller may not know how it was presented, so it may not know the best way to dismiss itself either.
I have a UINavigation controller setup. I was hoping to do this:
From one of the views, I presentModelViewController:animated:, the user selects one of three options, after selecting I want the UINavigationController behind the modal view to change (the user will not see this), then I want to dismissModalViewControllerAnimated to reveal the new view.
Is this possible using the built-in modal view? Or will I need to create a view, add/animate it to the rootViewController so its not in the same stack as the UINavigationController?
Thanks!
A modal view is a view you show modally on top of another view to interrupt the user from the current task. If I understand you correctly, you need two modal views and the selection user make on first modal view will decide what will show as the second modal view. Is that right?
If that's the case, you can make your main view to be the delegate of your first modal view, and send data back to the main view when the user makes a selection, and then main view dismiss the modal view (it's the main view's responsibility to dismiss it). And then based on user's input, you create another view and pop it modally. To make it animate correctly, you need to set the animation of the dismissing of the first modal view to be NO, and then make the animation of populating second modal view to be YES.
Hope this helps.
I'm having a very strange problem with the UINavigationController.
I found a very similar question here:
UINavigationController not popping UINavigationBar items
but the solution there had to do with the fact that the guy had added a category to NSMutableArray, and I'm not doing anything like that.
In short, the problem is this: I have a navigation controller and I'm pushing a few view controllers on it. Then when the 'back' button is tapped the view controller is popped, but the corresponding navigation item isn't. If I tap back again, then the navigation item is popped.
Besides, it only happens when using the back button from the navigation controller's navigation bar. If I call popViewController explicitly (for example from a button press), it works as expected.
And this only happens on my iPad running OS 3.2, but not on my iPod Touch running OS 3.0 or on the simulator.
I've been trying to isolate the problem in a separate project from the rest of my app so I can experiment with it, but I can't get it to reproduce, though it occurs 100% of the times on specific views in my app.
I know that's not nearly enough information to get an specific answer, but I just wanted to know if anyone ever heard of a navigation controller not popping the navigation items as expected, just so I could have some clue as to where to investigate next.
Here's an example of the code I use to push a view controller, it's pretty straightforward, I'm not trying to do anything special with it:
// pushing a view controller from a button press (set up with interface builder)
- (IBAction) tappedExtras
{
ExtrasViewController *controller = [[ExtrasViewController alloc] initWithNibName:#"ExtrasViewController" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
note: in that example I'm using a custom view controller class called ExtrasViewController, but the problem happened with any kind of view controller I tried.
And here's a bit of code used to pop the view controller explicitly, also triggered by a button press set up with interface builder:
- (IBAction) cancelChanges
{
userCancelled = YES;
[self.navigationController popViewControllerAnimated:YES];
}
this works perfectly (popping the view controller explicitly), but on the exact same view controller if instead of tapping the button set up with interface builder you tap the back button on the navigation bar, the navigation item is not popped correctly.
I got the same issue with navigation that subsist after poping the third level pushed view controller.
The issue only appear in landscape on iPad. No issue on the iPhone (3.1.3 & 4.0). Of course, it's ok on the simulator.
I've been reading the Head First iPhone Development book and I understand how to get to a new view from a table but how exactly would I be able to get to a new view or view controller, by just simply pressing a button? Is that even possible?
I mean there are some apps where you click a button, not a table cell and it loads a new view. How exactly is that done? If someone could help out a newbie it would be greatly appreciated!
I think what you're looking for is a modal vew controller. THis presents a modal view like you described on top of everything else. If rootViewController is the view controller that is displaying your current view, and myNewViewController the view controller you want to display modally:
[rootViewController presentModalViewController:myNewViewController animated:YES];
There's plenty of examples of this kind of thing on the net, just search for presentModalViewController
Like bpapa said in the comments, it's hard to be specific without code. However, generally what you want to do is:
Build a navigation controller that contains one original view.
Create a button in your original view using the Interface Builder.
Build a callback method (usually defined with IBAction) that is run when the button is pushed.
In that callback method, create a new view and push it onto the navigation controller the same way you would using a table view cell.
Alternately, if you only want one level of hierarchy, you could use a modal view controller; instead of pushing onto the navigation controller in the last step, just present the modal view controller.
The general answer is that you have an object that manages which view controller loads when.
The most commonly used is the UINavigationController. It is a UIViewController that instead of controlling views, controls other view controllers. It works like a simple stack. You push views you want to display onto the nav's controller stack and when you want them to disappear you pop them off.
A common (though sloppy) way of using a nav is to make it a property of your app delegate. Then anywhere in your app you can references it by:
UINavigationController *nav=[[[UIApplication sharedApplication] delegate] navigationController];
The view controller for the first the user sees is held in the nav's topViewController property. If you want to load a view based on a user action in the topViewController.view, you would have something like this:
- (IBAction) loadNextView:(id) sender{ // Action called by a a UI event such as a button press.
UINavigationController *nav=[[[UIApplication sharedApplication] delegate] navigationController];
UIViewController *nextViewController=...// load from nib, connect with IBOutlet, create programmatically
[nav pushViewController:nextView animated:YES];
}
The first view disappears to be replaced by the next one. To return to the first view, you have a method in the next view controller like so:
- (IBAction) unloadSelf:(id) sender{ // Action called by a a UI event such as a button press.
UINavigationController *nav=[[[UIApplication sharedApplication] delegate] navigationController];
[nav popViewControllerAnimated:YES];
}
... and the nav returns you automatically to the previous view regardless of what that view was.
When you first start out, especially if you use Interface Builder, the structure of the app is largely hidden. Behind the scenes all view controllers and their views exist in a hierarchy of some kind that leads back up to the app delegate. You should train yourself to think in hierarchal terms even if it is not immediately obvious how that hierarchy is constructed.