I have a login screen as my root view controller. If the user is already logged in, I want to skip over the login screen and show the main view controller.
The code below does that, but it shows a back button in the nav bar instead of the default nav bar.
Is there a way to remove the back button? There is a menu button that is supposed to be there, so simply hiding the back button will not suffice.
Thanks!
- (void)viewDidLoad {
if(GetUserName != nil){
[self pushingView:YES];
}
[super viewDidLoad];
}
-(void)pushingView:(BOOL)animation{
MainViewController *revealViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"RevealViewController"];
[self.navigationController pushViewController:revealViewController animated:animation];
}
Don't try to remove the back button, instead remove the need for the back button. Instead of using pushViewController:animated: use setViewControllers:animated:. In this way you only have one view controller on the stack (and you save the memory of keeping the view controller in existence).
Ideally you wouldn't even load the login view controller and then you'd save even more memory and time.
Related
As shown in the photo below, I have a TabBar controller as my root view controller with some navigation controller attached to it. In my VC1 and VC2, I have the tab bar and navigation bar on screen which is what I want, However, for VC3, I do not want tab bar. Currenty I am just hiding and unhiding the tabbar at view will appear. However, this presented some poor user interface. What I think would be great is when I present VC3, it just present "over" the current screen whilst keeping the navigation bar. Is it possible to do that? I'd also like the presentation to be from right to left just like a segue (As oppose to show from bottom)
Note. I use performSegueWithIdentifier for going to VC3
I have seen some solution where I have to set the rootVC to be a normal view controller instead (A login VC in my case) . However, I am trying to avoid that because If the user has already logged in, I do not need to present the login. If I have that as my rootVC all the time, the user will be forced to load and "see" the login VC first before seeing the tabBarVC. This will cause. Unless there is a way to get away with it?
FIRST WAY : PUSH
You can hide bottom bar on push by enabling the flag of VC3 from storyboard.
Please refer following picture:
SECOND WAY : PRESENT
Set a navigation controller for VC3 and present that navigation controller from VC1 or VC2 or TabBar as shown in following image :
You can create a new window, then present your VC3 on it, this would ensure it's over tabbar, in exchange of making new navigation controller and fake back button. But I'd rather check the hide tabbar on push option in storyboard, it give the tabbar hiding a nice animation
For your second question, the best way is make the rootVC in storyboard the tabbar controller, and separate the loginVC, in AppDelegate, check for user login or not and set the rootVC to loginVC or tabbar controller
When first time you login, you have to set the root view controller as login view controller.Then in viedDidLoad method you have to set check already logged in or not.When first run your app it has not logged in so you can go login page.Once you logged in you can go to next page directly.You can use LoginViewController viewDidLoad method.
- (void)viewDidLoad
{
[super viewDidLoad];
BOOL loggedIn = [[NSUserDefaults standardUserDefaults] boolForKey:#"logged_in"];
if(loggedIn)
{
NSLog(#"It has already logged in so go to next view");
}
}
When you login successfully set the bool to YES
- (IBAction)actionLoggin:(id)sender
{
if ([strUsername isEqualToString:#"xxxxxx"] && [strPassword isEqualToString:#"xxxxxx"]) //If it is correct
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"logged_in"];
}
}
Then when you log out,set the bool to NO
- (IBAction)actionLoggin:(id)sender
{
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"logged_in"];
}
1>For tab bar you can delete Tabbar or you can Hide Tabbar from storyboard but don't take separate nav controller for VC3.
You can kept navbar item title value of VC3 as VC2 or VC1 navbar title while pushing or presenting VC3.For that you have to user performseguewithidentifier and initialise VC3 nabber item title value
2> Hey for user is already login then in appdelgate you can change root view controller.By finding user is logged in or not from user default.
you can change rootviewcontroller using window.rootviewcontroller and while doing log out you again can change rootviewcontroller.
I have three View Controllers in a Navigation Controller. One is the root, and the others should appear if conditionA or conditionB is met, respectively.
In case both conditions are true, I want the conditionA View Controller to be shown. If things then change, and conditionA is no longer met, but conditionB still is, I want to show the conditionB View Controller. This means that I want to be able to go from the conditionA View Controller to the conditionB View Controller, and vice versa, until neither condition is met. However, I always want the back button to send users to the root.
To implement this while avoiding errors like ‘Finishing up a navigation transition in an unexpected state’, I’ve taken code from Dave DeLong’s answer https://stackoverflow.com/a/11821263/2524427.
(void)somethingChanged:(NSNotification*)notification
{
if(!conditionA && !conditionB){return;}
NSArray *viewControllers = self.navigationController.viewControllers;
NSMutableArray *newViewControllers = [NSMutableArray array];
// preserve the root view controller
[newViewControllers addObject:[viewControllers objectAtIndex:0]];
if(conditionA)
{
// add the new view controller
[newViewControllers addObject:[self.storyboard instantiateViewControllerWithIdentifier:#"conditionAViewController"]];
// animatedly change the navigation stack
[self.navigationController setViewControllers:newViewControllers animated:YES];
return;
}
if(conditionB)
{
// add the new view controller
[newViewControllers addObject:[self.storyboard instantiateViewControllerWithIdentifier:#"conditionBViewController"]];
// animatedly change the navigation stack
[self.navigationController setViewControllers:newViewControllers animated:YES];
}
}
This works almost perfectly. However, if I have the following sequence
somethingChanged triggered while only conditionB is met -> conditionB View Controller appears - as desired
somethingChanged triggered again, but now both conditionA and conditionB are met -> condition A View Controller appears - as desired
somethingChanged triggered for the third time, now back to initial situation where only conditionB is met -> I return to the root View Controller (with Back button) instead of conditionB View Controller…
How can I keep going back and forth between these View Controllers?
Instead of the solution in the question you linked. Try this
init your own back button UIBarButtonItem as navigationBar's leftBarButtonItem in both conditionA View Controller and conditionB view controller
wire up with a action
- (IBAction)dismiss:(id)sender {
[self.navigationController popToRootViewControllerAnimated:YES];
}
I am developing an iOS application that uses a left side slide out drawer containing tabs, each representing one of the main views of the app. Currently, when the user selects a tab the application searches through the navigation stack for an instance of the relevant view controller and if it finds one pops back to that controller, otherwise it creates a new instance and pushes it onto the stack.
I would like to also add a back button allowing the user to go back to the previous view, however since many navigation options will pop the user to a previous view controller resulting in the controller they are leaving being dealloc'ed there is no obvious way to have a back button to get back to that controller again.
Is there any way to structure this application so that a back button can be added, while still allowing the user to use the tabs to navigate to any view at a given time?
An example of the navigation code follows (invoked when a user clicks one of the tabs):
if(![self.navigation.topViewController isKindOfClass:[GraphViewController class]]) { //Are we already in this view?
BOOL foundController = NO;
for(id controller in self.navigation.viewControllers) { //Is there a controller of this type already in the stack?
if([controller isKindOfClass:[GraphViewController class]]) {
[self.navigation popToViewController:controller animated:YES];
foundController = YES;
break;
}
}
if(!foundController) {
GraphViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"graphViewController"];
controller.connection = _connection;
controller.data = _dataCache;
[self.navigation pushViewController:controller animated:YES];
}
}
I believe what you want is navigation controllers for each item in the slide out menu. This way when the user selects a view from the side menu they can navigate the views associated with that section. This will allow the user to go back from a view once they have selected a item from the side menu.
I have a popover that has a main view that is used to pick from several sub-views and I'd like to reset the popover to the main view when the user taps outside of the popover and closes the window.
For example, the main popover view has Options, Categories, WordList, and Results. I'd like to make it so that the next time the user invokes the popover, they go to the main view rather than back to the view they were on when they last closed the popover.
If I'm only one level deep, I can use
- (void)viewWillDisappear:(BOOL)animated {
[[self navigationController] popToRootViewControllerAnimated:YES];
[super viewWillDisappear:animated];
}
But if I'm deep in a hierarchy, e.g. WordList:Category:Words I can't pop to root in WordList or Category since when the view disappears, I want to go to the next level down. If I use the code listed above, I can't get down a level. I pop to the root view.
What I'd like is to be able to tell the popover view to pop to its root when it's dismissed. Something like this:
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
[[self popover] popToRootViewControllerAnimated:YES];
[self.popoverController dismissPopoverAnimated:YES];
}
Any thoughts?
I believe that what you want is UIPopoverController's contentViewController property, which will be whatever view controller you initialized the popover with--most likely that navigation controller. This...
[self.popover.contentViewController popToRootViewControllerAnimated:YES];
...should do the trick for you.
When initializing the popover, I test to see if it already exists. If so, I skip the initialization and go directly to the popover. That's why, when the popover is dismissed, it stays in whatever view the user left it in.
To make it start at the first view, I just need to set the popover to nil.
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popOverController {
[self.popoverController dismissPopoverAnimated:YES];
self.popoverController = nil;
Now when the user invokes the popover, it creates a new set of views, starting with the main menu.
I have a login view in my application which loads the main menu view after the user enters the correct username and password. I'm using this to go to main menu view:
MenuViewController *menuViewController=[[MenuViewController alloc] initWithNibName:#"MenuViewController" bundle:nil];
menuViewController.title=#"Felton";
UINavigationController *tnavController=[[UINavigationController alloc] initWithRootViewController:menuViewController];
tnavController.view.frame=CGRectMake(0, 0, 1024, 748);
[menuViewController release];
self.navController=tnavController;
[navController release];
for(UIView *subview in self.view.subviews)
{
[subview removeFromSuperview];
}
[self.view addSubview:self.navController.view];
So my question is how exactly am I going to go back to the login page when the logout button is pressed. I've tried the same way as above but the problem I have is that each time the user presses the logout button the login page gets 1 navigation bar, and they pile on each other each time. Is there any way that I can stop this from happening? Because, my login page shouldn't have a navigation bar.
thanx in advance
Although it's not clear from your question what the exact flow through your app is, you certainly shouldn't be adding the navController view as a subview.
You'd be better placed to have the main menu as the rootViewController of your main window, and then present the login view controller on top of it (using presentModalViewController:).
Create a delegate protocol in your login view controller, and make the main menu the delegate. WHen they login, the delegate method fires, and the main menu dismisses the login view. When they log out, the main menu can present the login view again.