Consequences of Bad Programming: dismissViewController vs popViewController

Emin Israfil iOS picture Emin Israfil iOS · Oct 29, 2013 · Viewed 11k times · Source

I understand the difference between dismissViewControllerAnimated:completion: and popViewControllerAnimated:, as described on Stack Overflow and here:

-dismissViewControllerAnimated:completion: method is used to dismiss an UIViewController, which was presented by the method: -presentViewController:animated:completion:.

-popViewControllerAnimated: method of UINavigationController is used to pop a controller shown by -pushViewController:animated method of UINavigationController.

I recently caught a mistake in my app, where I was using [self dismissViewControllerAnimated:completion:] to dismiss a VC that was presented with a push in a navigation embedded app. I french fried when I should have pizza'd. I didn't catch the mistake because everything worked fine and my VC was deallocated as expected.

My question: What are the consequences of mixing these two methods up?

Answer

Tommy picture Tommy · Oct 29, 2013

-presentViewController:animated:completion: and -pushViewController:animated: mean different things. The former says "present this other view controller so as to replace yourself". The latter says "show this other view controller within yourself, as part of the list you're controlling".

So it's about who is considered to be in charge of the display after the transition. In the former case the navigation controller surrenders control. In the latter it retains control.

The former functionality is provided by UIViewController. The latter is specific to UINavigationController.

Because the two actions are quite different, the opposite actions are separate. Navigation controllers could catch dismissViewController:... and check how the named controller was presented, branching either into the superclass or into pop... but the conflation of tasks would be unappealing from a design and a maintenance point of view.

Since the navigation controller doesn't promise to map the one thing to the other, and UIViewController doesn't promise any particular behaviour if the controller you pass hasn't previously been presented, I think the literal answer to your question is: the consequence of mixing these two things up is undefined behaviour.