0

I have an issue with the presentViewControllerfunction.

I have a login menu (A) and a button who display a login form (B). On success login, I present a third view with self.presentViewController (C).

Login menu (A) -> Login form (B) -> Content (C)

It's work, I can present the third view (C) but the login menu (A) is always visible (I can see it in UI Debug mod).

So, how to close the A ViewController?

YoannLth
  • 197
  • 2
  • 14
  • After the login dismiss the present view controller in ->content (C) – Sanjeet Verma Oct 18 '16 at 13:00
  • Have you tried self.navigationController dismiss?? – Sheereen S Oct 18 '16 at 13:03
  • This is the way presentViewController works. If you are presenting B from A, It doesn't mean it will close the A. In you case if you want to "Content" to be rootController, Then you have to change window.rootviewcontroller = yourviewcontroller. – Wolverine Oct 18 '16 at 13:06
  • you may need to change the order of the hierarchy probably to a most logical one, like e.g. _Content_ (A) ➜ _Login Menu_ (B) ➜ _Login Form_ (C), so when you dismiss the to login forms and views, it falls back to the _Content_ (A) as it should be. – holex Oct 18 '16 at 13:12
  • And if you want to go with more advance level coding, Then you can also use ContainerView. – Wolverine Oct 18 '16 at 13:12
  • 2
    http://stackoverflow.com/questions/19962276/best-practices-for-storyboard-login-screen-handling-clearing-of-data-upon-logou Refer for best practices – Wolverine Oct 18 '16 at 13:14

3 Answers3

1

presentViewController, presents a view controller modally. In other words, over the current view controller’s content, and the current view controller will not get deallocated.

Use the following code for your sample:

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: <Identifier as in Storyboard of C>)
(UIApplication.shared.delegate as! AppDelegate).window?.rootViewController = vc

If you would like to include a transition, you could replace the last line with something as the following:

UIView.transition(from: currentRootViewController!.view, to: vc.view, duration: 0.8, options: .transitionCrossDissolve, completion: { (_) in
      (UIApplication.shared.delegate as! AppDelegate).window?.rootViewController = vc
})
Carien van Zyl
  • 2,853
  • 22
  • 30
  • @YoannLth : This is the way you can change the root-controller – Wolverine Oct 18 '16 at 13:08
  • the OP's post seems to be an [XY Problem](http://xyproblem.info), therefore you need to resolve problem X for him, not offering an overcomplicated solution for problem Y, maybe. – holex Oct 18 '16 at 13:17
  • I tried with this answer @Wolverine but it didn't work. I fixed the problem with a dirty hack I think : I dismiss all view controllers with `self.view.window!.rootViewController?.dismissViewControllerA‌​nimated(false, completion: nil)` and it return to the app entry point which is a ViewController who check if user is logged in. – YoannLth Oct 18 '16 at 14:36
  • @YoannLth, I simplified the solution as holex suggested. I think the problem with my explanation for you was that I pointed towards the initialVC, whereas your C is probably not your initialVC. – Carien van Zyl Oct 18 '16 at 14:55
1

If we consider the presentVieController mechanism, this is not a problem or bug. Still if you feel that you don not want your previous controller's remain in Hierarchy, Then you have to change the flow.

Currently your flow is :

A -> RootViewController. B -> LoginScreen C -> Container

I would suggest to refer below answer for best practise.

Best practices for Storyboard login screen, handling clearing of data upon logout

if you give thoughts on handling the flow, you can solve your problem. here are my suggestions

Suggestions :

  1. You set C as a rootController, In C's ViewDidLoad , you check weather User is logged in or not, If user is not logged in, you can present A , And From there you can present B. Once you successfully get logged in, you can dismiss A and B And refresh your rootController C as per logged user values.

To dismiss multiple view controller, you can try below code

-(void)dismissModalStack {
    UIViewController *vc = self.presentingViewController;
    while (vc.presentingViewController) {
        vc = vc.presentingViewController;
    }
    [vc dismissViewControllerAnimated:YES completion:NULL];
}
  1. You can also use the ContainerView mechanism, You set C as rootController, And in C , you take an ContainerView In which you can show the A And B and after login, you can remove them and refresh C.

Hope it Helps!

Community
  • 1
  • 1
Wolverine
  • 4,264
  • 1
  • 27
  • 49
0

I think this tutorial has your answer https://www.youtube.com/watch?v=WIaRs2d6Xm0