0
votes

I spent so many hours with this issue, so I can't find any solution.

I open SettingsViewController from my TopBar on tap in avatar with pushViewController method (here is problem) and from menu (not modal).

I want to dismiss this pushed ViewController when I tap on logout button.

Below is a function that I use in some VC's and works very well.

func goToSettingsView() {
    let vc = SettingsViewController(nibName: "SettingsViewController", bundle: nil)
    vc.modalPresentationStyle = .fullScreen
    self.navigationController!.pushViewController(vc, animated: true)
    for constraint in vc.view.constraints {
        if constraint.identifier == "alignTopHeader" {
           constraint.constant = 0
        }
    }
}

When I clicked logout button isn't working and when I login from (LoginViewController) this SettingsViewController is still showing, but I would go to Main Screen without any modals.

I did some ideas but not good working yet.

First idea was:

Below is my logout IBaction in my SettingsViewController:

- (void)logout {
    [self dismissViewControllerAnimated:YES completion:nil];
    [[UserManager shared] logoutUserWithSuccessBlock:^{
        [self presentLoginViewController];
    }];
}

LoginViewController is dismiss, but self is targeted for SettingsViewController?

Second idea:

I added a function declared in AppDelegate "backToRoot" in LoginViewController and call from viewWillDisappear.

[appDelegate backToRoot];

function in AppDelegate.m file

-(void)backToRoot {
   [self.navigationController dismissViewControllerAnimated:YES completion:nil];
   PresentationsPickerViewController *mainvc = [[PresentationsPickerViewController alloc] init];
   [self setCenterPanelWithViewController:mainvc];
}

But still not working with modal, it's work fine when SettingsViewController isn't modal.

Do you have any ideas how to hide/dismiss pushed SettingsViewController in logout action?

3

3 Answers

1
votes

It's really simple. If you want to dismiss a pushed UIViewController in a navigational-stack just pop it out, like this:

func logout() {
    navigationController?.popViewController(animated: true)
}
1
votes

I want to dismiss this pushed ViewController when I tap on logout button.

Now you don't dismiss a pushed UIViewController. Push is a navigation style associated with a UINavigationController. When you push a UIViewController you need to pop it.

When we talk about dismiss, we usually mean closing a UIViewController that is presented modally. This method means that a new UIViewController is added on top of your previously shown UIViewController or any class inheriting from it. This does not get added onto the navigation stack. You can only dismiss a UIViewController if it was presented.

Now your first code block shows you pushing the SettingsViewController and your first solution tries to dismiss it. This will not work. You need to pop it from the UINavigationController to close it.

Next,

LoginViewController is dismiss, but self is targeted for SettingsViewController?

The method [self dismiss]... will close the screen that is the latest presented screen on top. If you present LoginViewController from settings, then LoginViewController screen gets dismissed.

Also,

But still not working with modal, it's work fine when SettingsViewController isn't modal. Do you have any ideas how to hide/dismiss pushed SettingsViewController in logout action?

If your SettingsViewController is presented then you need to dismiss it and if it is pushed, you need to pop it.

If there are situations when both the actions can occur, then on your close button action, you can check how the screen was displayed. Use this link to figure out the checks for that.

If all you want to do is go to your LoginViewController on logging out, you can just change the root window of your application.

let window = (UIApplication.shared.delegate as? AppDelegate)?.window
window?.rootViewController = viewController //this will be your loginViewController
window?.makeKeyAndVisible()

For iOS 13:

UIApplication.shared.windows.first?.rootViewController = LoginViewController
UIApplication.shared.windows.first?.makeKeyAndVisible()
0
votes

You can simple dismiss all view controllers above the root view controller.

func logout() {
  self.view.window!.rootViewController?.dismiss(animated: false, completion: nil)
}

Hope it will help. Thanks.