Kaz
Kaz

Reputation: 1466

Hide all modal view controllers

i've a login view presented as a ModelViewController and i have a register view presented as a NavigationControlloer on top of it:

Login (ModelViewController) ---->Register(NavigationController)

i'm presenting the Register view(CreateAccount) at the Loginview as follow:

createAccount= [[CreateAccount alloc] initWithNibName:@"CreateAccount" bundle:nil];

navController = [[UINavigationController alloc] initWithRootViewController:createAccount];

UIBarButtonItem *cancelButtun=[[UIBarButtonItem alloc]initWithTitle:@"Cancel" style:UIBarButtonItemStyleBordered target:self action:@selector(HideMe)];

UIBarButtonItem *registerButtun=[[UIBarButtonItem alloc]initWithTitle:@"Register" style:UIBarButtonItemStyleBordered target:self action:@selector(Register)];

createAccount.navigationItem.leftBarButtonItem = cancelButtun;
createAccount.navigationItem.rightBarButtonItem=registerButtun;
createAccount.title=@"Create Account";

[self presentModalViewController:navController animated:YES];

the login controller has the NSURLConnectionDelegate for booth the login and the register. when registration finishs i simply call the

[self dismissModalViewControllerAnimated:YES];

which will dismiss the registration view only.

i want to dismiss the login view also so i can go back to my main application.

Upvotes: 10

Views: 15503

Answers (7)

Dimple Shah
Dimple Shah

Reputation: 303

[[[[UIApplication sharedApplication] keyWindow] rootViewController] dismissViewControllerAnimated:true completion:nil];

Dismiss all controllers except RootViewController..

Upvotes: 0

JorMan
JorMan

Reputation: 1

while(self.presentedViewController)
        [self.presentedViewController dismissViewControllerAnimated:NO completion:nil];

Worked to dismiss all in iOS 7

Upvotes: -1

zurbergram
zurbergram

Reputation: 429

Place this method in your app delegate and it will remove all view controllers that have a presentedViewController which means that they were presented modally

-(void)dismissModalViews
{
    if (self.window.rootViewController.presentedViewController) {
        [self.window.rootViewController.presentedViewController dismissViewControllerAnimated:NO completion:nil];
        [self performSelector:@selector(dismissModalViews) withObject:nil afterDelay:0.5];
    }
}

Upvotes: -1

superjessi
superjessi

Reputation: 1790

Check out my answer to a similar question here: Dismissing ModalViewController of ModalViewController

I am using pretty much the same thing as you in my app, and this solution works for me. Please be sure to read the comments as well, since one of the references changed with iOS5.

Edit: In order to dismiss a modal view that is presented over another modal view, you have to call dismissModalViewControllerAnimated: on the parent of the parent.

iOS <5.0

[[[self parentViewController] parentViewController] dismissModalViewControllerAnimated:YES];

iOS 5.0+ (must change all references to parentViewController to presentingViewController)

[[[self presentingViewController] presentingViewController] dismissModalViewControllerAnimated:YES];

Upvotes: 20

Mark Adams
Mark Adams

Reputation: 30846

The primary problem at hand is that the login view controller is completely unaware of when the registration view is dismissed and we can handle that with delegation.

First declare a protocol and a delegate property on registration view controller.

@protocol CreateAccountDelegate;

@interface CreateAccount : UIViewController

@property (nonatomic, assign) id <CreateAccountDelegate> delegate;

@end

@protocol CreateAccountDelegate <NSObject>

- (void)createAccountViewControllerDidFinish:(CreateAccount *)controller;

@end

Next, make the login view controller the delegate of the registration controller.

createAccount = [[CreateAccount alloc] initWithNibName:@"CreateAccount" bundle:nil];
createAccount.delegate = self;

And implement -createAccountViewControllerDidFinish:

- (void)createAccountViewControllerDidFinish:(CreateAccount *)controller
{
    [self dismissModalViewControllerAnimated:YES];
}

Finally, when you dismiss from within the registration controller, message the delegate to inform it if your imminent dismissal.

[self.delegate createAccountViewControllerDidFinish:self];
[self dismissModalViewControllerAnimated:YES];

Now, having said all of that. May I suggest an alteration to your design? I would present the login view controller as part of a navigation controller from the get go. Then if the user chooses to register, just push the registration view on to the controller. This way, no matter where you dismiss from, it will only have to dismiss the main navigation controller.

Upvotes: 1

XJones
XJones

Reputation: 21967

dismissModalViewControllerAnimated: dismisses all modal view controllers presented on top of the sender. To dismiss back to the view controller that presented the login controller, keep a reference to it and dismiss as follows:

[loginController dismissModalViewController:animated]

This is the brute force way of doing it. In my app where I did something similar I post various notifications corresponding to session (e.g. login) state and my login controller observes those notifications and dismisses itself appropriately.

Upvotes: 0

Srikar Appalaraju
Srikar Appalaraju

Reputation: 73608

Calling dismissModalViewController will, if the current view controller did not present any modal controllers, call the method on its parent instead. Calling the method on a view controller will dismiss all presented modal view controller to that controller. To illustrate:

If you have three view controllers: vc1, vc2 and vc3 and vc1 is the main/currently used view controller.

  1. In vc1 you present modal vc2. In vc2 you then call dismiss, because there are no modal vcs presented from vc2, the dismiss message is passed to the parent (vc1) which dismisses vc2, and you're back at vc1.

  2. In vc1 you present modal vc2, then from vc2 present modal vc3. Calling dismiss in vc3 will send the message to its parent (vc2) which will dismiss vc3. To dismiss vc2 and vc3 at the same time, you need to call dismiss in vc1, this will dismiss all (both) modal view controllers. If dismissing animated, only the first one will be animated.

One of the best ways to solve this is to use a navigation controller through-out. i.e. instead of using modalViews initially to present login view, use navigationViewcontroller there itself. If you need to present registration page. Push that view. If you need to goto the initial view (i.e. apart from loginView or registrationView), then use popToRootViewControllerAnimated method in navigationViewcontroller.

Upvotes: 23

Related Questions