1

I start with a UITabBarController (VC1)

I then present a UIViewController(VC2) on top of it and set its variable named parentController to self:

let loginController = LoginController()
DispatchQueue.main.async {
    self.present(loginController, animated: false, completion: {
        // Once presented, set parentController = self
        loginController.parentController = self
    })
}

I then continue to present a third UIViewController(VC3) on top of VC2 when the user taps a "Login with email button":

let withEmailController = WithEmailLoginController()
withEmailController.parentController = self
present(withEmailController, animated: true, completion: nil)

After signing up with email, I present a fourth UIViewController(VC4) so the user can pick their profile picture

let profilePicturePickerController = ProfilePicturePickerController()
profilePicturePickerController.parentController = self
present(profilePicturePickerController, animated: true, completion: nil)

After the user has picked their profile picture I call this code in VC4 in attempt to dismiss VC2, VC3, and VC4 from a function in VC2:

parentController?.parentController?.handleDismiss()

Where handleDismiss in VC2 is simply:

func handleDismiss() {
    // Progress MainTabBarController
    parentController?.progressWithLoggedInUser()
    // Dismiss the LoginController
    self.dismiss(animated: true) {
        // I do some things in here that aren't relevant to the question
    }
}

The Problem: When the function belonging to VC2 named handleDismiss is called from VC2, everything works fine and VC2 is dismissed (VC3 and VC4 are not dismissed because they have not been presented yet). However, when handleDismiss is called from VC4 as it is above, only VC3 and VC4 are dismissed. VC2 remains. VC1,2,3,4 are all in the same stack, to my understanding.

What I have tried: Putting all present/ dismiss commands in DispatchQueue.main.async {code}. Calling parentController?.parentController?.dismiss(animated: true, completion: nil) directly in VC4 has the same error. Calling handleDismiss() from VC2 to make sure it works properly

Where else I have looked: Dismiss more than one view controller simultaneously, Dismissing a Presented View Controller. I feel that setting those parentController variables is the same as using presentingViewController

Sanzio Angeli
  • 1,441
  • 11
  • 26

1 Answers1

0

Okay turns out that re-reading the apple documentation is a good idea

The Answer: My understanding now is that calling dismiss on a UIViewController does two different things depending on whether the controller has any children (controllers presented on top of it). If you call dismiss on the very top view controller i.e. topController.dismiss(animated: true){code} it will dismiss that top controller as expected. If, however, you call dismiss on a controller that has children, it will dismiss all children of that controller, but not that controller itself. The top most child is the only one that animates.

If you are calling dismiss in a stack, you must call it on the parent of the child you want to dismiss: parentController.dismiss(animated: true){code}

Implemented Solution: The function handleDismiss() has been moved into VC1 and that fixes everything.

Sanzio Angeli
  • 1,441
  • 11
  • 26