I have created an application that has a Login.
It starts with a Welcome View Controller, checks if the user is logged in if not, opens a Login View Controller. If the user is logged in, or once they have it pushes the user to the Home View Controller like this.
App Delegate (did finish launching)
self.welcomeViewController = [[APPWelcomeViewController alloc] init];
self.homeViewController = [[APPHomeViewController alloc] initWithNibName:#"APPHomeViewController" bundle:nil];
self.navController = [[UINavigationController alloc] initWithRootViewController:self.welcomeViewController];
self.navController.navigationBarHidden = YES;
self.window.rootViewController = self.navController;
Once the user is logged in it pushes the home view.
// Push the homeViewController onto the navController
[self.navController pushViewController:self.homeViewController animated:YES];
This all works fine up to this point. I then use a modal view controller for the Setting, which includes a button to Logout. The logout of the user runs this:
// Log the user out
[User logOut];
// Then we need to remove the Settings Modal View Conrtoller
[self.presentingViewController dismissModalViewControllerAnimated:YES];
// Then we need to take user back to welcomeViewController
[self.navigationController pushViewController:welcomeViewController animated:YES];
It dismisses the Settings View controller as expected, but the navigation controller remains on the Home view. There is no error, does anyone know why this is not working correctly?
Resolved by re-arranging code. Searching for current user on the appdelegate instead then either loading the nav controller with the root controller of home view or running a method to load the welcome view controller.
The welcome view controller then checks for user as well, if not current user it presents the modal login view controller
you dont need to push navigation controller, once you init your window with the navigation controller that contain the welcome view controller.
if you want to add more view inside this stack (inside welcome view controller) you call method self.navigation controller pushviewcontroller ... if you want to remove from stack, call popviewcontroller..you ll go to your main view stack (root).
Try this:
// Take me back to the root navigation view controller (APPWelcomeViewController)
[self.navigationController popToRootViewControllerAnimated:YES];
Related
Here is the scenario:
The first scene in my storyboard is a login view. It's a UIViewController. When the user is logged in, it shows the home view which is embedded in a navigation controller. I'm adding a log out functionality which should take me back to the first scene in the storyboard which is the login view. How do I do that?
Here is an image of the storyboard showing the login view -> navigation controller -> home view
This is my implementation so far. In the log out action, I clear the session, and pop to root view controller. It does not work because I am still stuck on the home view since it is the root view controller of the navigation controller. However, If I restart the app, the user is logged out and I'm left with the login view.
Code:
[self.navigationController popToRootViewControllerAnimated:NO];
// Set at beginning of storyboard
UIStoryboard *mystoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate];
app.loginViewController = [mystoryboard instantiateViewControllerWithIdentifier:#"loginViewController"];
Use unwind segues for that.
In your LoginViewController, declare a method with this signature
- (IBAction)unwindToLoginViewController:(UIStoryboardSegue*)segue
Go to your HomeViewController and control drag from your logout button to the Exit button at the top of your view controller window (see screenshot below), then select the unwindToLoginViewController segue. That's it!
U can pop by using navigationController.viewControllers.Get all View Controllers among navigationController,identify it and then pop.If u have pushed the segue from LoginView to HomeView
if([self.navigationController.viewControllers[0] isKindOfClass:[LoginViewController class]])
{
[self.navigationController popToViewController:self.navigationController.viewControllers[0] animated:YES];
}
Hope it helps you...
Try this answer. First you create a navigation controller. make it "is initial View Controller". After that connect login Viewcontroller as a root view controller And connect home controller with facebook button Action.
Navigation Controller -> Login Controller -> Home Controller
Your Storyboard is look like this
After that when you logout from HomeViewController then Just add this method:
-(IBAction)logOut_Action:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
Its working Fine. Please implement like this and let me know if you face any problem. :)
Try this:
[self.view.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
I am using SwReveal view controller.It is initially set as root view controller. I am using a Login screen when app logged in I remember the user name and next time when the app is opened i set a main screen as Root view controller. But here where my problem starts. When i set main screen as Root view controller SWREVEAL view controller is no longer my root view controller. How to set SWRevealController back to Root view controller in Main screen View did load method.
Here is how i set main screen as Root view controller
TimeTableViewController * time = (TimeTableViewController *)[sb instantiateViewControllerWithIdentifier:#"Time"];
navigation = [[UINavigationController alloc]initWithRootViewController:time];
self.window.rootViewController = navigation;
// [self.window setRootViewController:navigation];
[self.window addSubview:navigation.view];
[self.window makeKeyAndVisible];
Here is how my Reveal view controller is set.. its in Main Screen View did load method. But becoz of i changed the root view controller from "SWREVALVIEWCONTROLLER" to "Main screen" view controller the below code doesnt work and doest open up the reveal. Please help
LearningSearchController *slideView = [[LearningSearchController alloc]init];
slideView.delegate = self;
[(LearningSearchController *)self.revealViewController.rightViewController setDelegate:self];
I think your problem is Login Screen. Keep SwRevealViewController as rootview controller and for login check in frontview screen. If user is not logged in then present LoginViewController. For example MainScreen is a frontview for SwRevealViewController then in viewdidLoad check user is already logged in or not.
I have a tab view controller with a navigation controller. In the first tab item I click on a button in a view that pops up a view with animated: YES.
Then when that view is done I hit another button that dismisses it. Like:
[self dismissViewControllerAnimated:NO completion:^{
ProfilesViewController *profile = [[ProfilesViewController alloc] init];
[self.navigationController pushViewController:profile animated:YES];
//SHOW YOUR NEW VIEW CONTROLLER HERE!
}];
But everytime this code runs, it dismisses the view, DOES NOT push the profiles controller, and shows the view from the first tab bar item.
How do I push the ProfilesViewController to the screen with a Back arrow?
If you are using dismissViewControllerAnimated to dismiss that means that the VC is presented modally. As such, it doesn't have a navigation controller (so self.navigationController is nil) and thus it can't push anything into the navigation controller.
You should really add a property to the controller which is a delegate or a completion block which can be used to push the controller from another controller (the one that presents it) to dismiss and push the controller.
A second option is to pass the navigation controller, it's a similar amount of code to using a block but not so good.
A crappy option is to use the parentViewController to find the appropriate navigation controller, but that sucks for many reasons.
Hi I am new to IOS development. I am developing small application I want to use split view. But that split view is not my root view. My application start with login which is not split view. After login I want to start my main view which is split view controller. So here is my problem if I set main view as root view i.e. start point for my application it works fine. But If I set my login controller as root controller then it gives exception. In my AppDelegate I am setting following things:
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *masterNavigationController = [splitViewController.viewControllers objectAtIndex:0];
SidePannelViewController *controller = (SidePannelViewController *)masterNavigationController.topViewController;
controller.splitViewController = splitViewController;
splitViewController.delegate = (id)controller;
once I set my main view as root controller it works fine. How to solve this problem? Need Help. I want to keep my login screen as normal login view controller and after login start split view controller. Thank you.
You can present the LoginScreen as modal over the top of the split view controller, else you can initially set LoginScreen as rootViewController and then replace with SplitViewController as rootController.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self performSegueWithIdentifier:#"showLogin" sender:self];
}
Once user logged in successfully dismiss the loginscreen.
Hope this helps.
You can set the LoginViewController as the root view controller when the user is not logged in and changed the root to split view if the user is logged in. Just put the check in didFinishLaunchingWithOptions method to check if the user is logged in or not and set your root accordingly.
I have a tab bar controller with a navigation controller per tab. The nav controllers have view controllers. I then have a Login View Controller not connected to the tab bar controller that I call with the code below if a user needs to login or logs out.
I am seeing some strange behavior when I try to conditionally push a view controller based on if a user is logged in or not.
My logic looks like this:
if(currentUser){
}else{
LoginViewController *svc = [self.storyboard instantiateViewControllerWithIdentifier:#"Login"];
svc.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:svc animated:YES];
}
When the view is pushed it look as if the the Login View is pushed and another Login View is pushed on top of it.
For logout I have the same code in a segue:
if ([segue.identifier isEqualToString:#"LogoutView"]) {
[self logOut];
LoginViewController *svc = [self.storyboard instantiateViewControllerWithIdentifier:#"Login"];
svc.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:svc animated:YES];
}
In this instance I see the same double push and each time I click my login button it pushes another Login View. This happens infinitely. I then get the warning:
Finishing up a navigation transition in an unexpected state.
Navigation Bar subview tree might get corrupted.
When I press back in the navigation, the app crashes with the error:
NSInvalidArgumentException', reason: 'Can't add self as subview'
Am I not correctly pushing the login view controller?
Segues instantiate new controllers, and perform the transition form the source controller to the destination controller. Therefore, you should neither be instantiating the controller in code, nor pushing it with pushViewController:animated:. If the buttons (rather than the controller) are triggering the segues, then you only need to get a reference to the destination controller (segue.destinationViewController), and use that to hide the bottom bar,
-(void)prepareForSegue:(UIStoryboardSegue *) segue sender:(id) sender {
if ([segue.identifier isEqualToString:#"LogoutView"]) {
[self logOut];
LoginViewController *svc = segue.destinationViewController;
svc.hidesBottomBarWhenPushed = YES;
}
}
If you need to do this conditionally, then the segue should be connected directly from the controller, not a button. Then you need to call performSegueWithIdentifier: in some method where you have the logic to determine which (or whether a) segue should be performed.