I currently have 3 ViewControllers: LoginViewController
, SignUpViewController
and MainViewController
.
When the user opens the app, LoginViewController
will be presented. If its the user's first time using the app then they will have to sign up, the "Sign Up" button is in the LoginViewController
. The "Sign Up" button will bring up the SignUpViewController
.
Once the user finished signing up. The MainViewController
will be presented.
What I am trying to do is. In the MainViewController
there will be a "Log Out" button. When the user press it the MainViewController
should be dismissed and LoginViewController
should be there. The user should not see the SignUpViewController
for the second time.
Here is what I have tried:
1) Dismiss SignUpViewController
and present MainViewController
in "sign up" button:
- (void) signUpClicked
{
MainViewController *mainViewController = [viewController.storyboard instantiateViewControllerWithIdentifier:@"MainViewController"];
[viewController presentViewController:mainViewController animated:YES completion:^{
[viewController dismissViewControllerAnimated:NO completion:^{
}];
}];
}
2) When MainViewController
loads, dismiss SignUpViewController
- (void)viewDidLoad
{
[super viewDidLoad];
SignUpViewController *signUpViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"SignUpViewController"];
[signUpViewController dismissViewControllerAnimated:NO completion:^{
}];
}
SOLUTION: Modifying the current navigation stack
The neatest way to solve this problem is by accessing the navigation controller Navigation stack. The navigation controller knows the flow by storing the controllers in an array where it stacks on an on the controllers. You can modify this stack by removing the undesired view controller once is safe to do so, this stack is represented on the property called
viewControllers
(NSArray). The safe way is to remove it from the array after is not the current view controller (or the top one on the stack) which you can check by looking at the propertyvisibleViewController
So your array should look like this when you already signedup and you are on the mainViewController:
[loginVC,SignUpVC,MainVC]
That means
MainVC
is thevisibleViewController
and it is safe to modify the navigation stack as long as you keep the samevisibleViewController
as the last item on your array.Since is not a Mutable Array just assign a new array to the
viewControllers
property with this[loginVC,MainVC]
. I will recommend at least taking a peak to the documentation on UINavigationController.presentViewController can get you a long ways, but maybe you should roll your own Container View Controller. They're pretty dang easy! The UIContainerViewControllerProtectedMethods category on UIViewController outlines what methods you can/should use.
The basic gist is you have a container View Controller that adds child View Controllers to itself and their views as subviews of its own view. The main method that does the heavy lifting is:
In the animations section, you can do whatever sort of movement you want. In your case, you would want to put the LoginViewController's view behind the MainViewController's view, and move the MainViewController's view offscreen. You get to supply your own animation options, so the appearance will move similarly to how dismissViewController looks now.
It's a bit more overhead to get set up, but View Controller Containment gives you a lot of flexibility and power.
Got it. I passed the SignUpViewController to the MainViewController and dismiss the SignUpViewController in the MainViewController.
For anyone else who had the same question as me.
SignUpViewController.m
MainViewController.m
This worked for me; it was extremely tedious getting the order correct.
This wasn't part of your question, but you should consider using a
UINavigationController
because it's probable that you will have to show new views from your MainViewController.The architecture I would use is the next:
So your first view controller is the LoginViewController.
In your SignupViewController, you implements the next protocol:
The
customData
object is only useful if you need to pass data from your SignupViewController to your MainViewController.And you add this property to your SignupViewController
Your LoginViewController now has to implement the protocol you just created.
And you should implement those methods like this
I'm explaining a little this code ^^ In your SignupViewController, when the user clicks on the button that ends the signup process, you call this method
Or if he cancels
With this method, your SignupViewController will be removed when you present your MainViewController. And when the user logouts, you will have to call this method in your MainViewController :
As your SignupViewController is already dismissed, you will be redirected yo your LoginViewController directly.