0
votes

When a UIViewController presents another view controller the simplest way for the presented view controller to dismiss itself when it is done under iOS 5 is to call:

[[self presentingViewController] dismissViewControllerAnimated:YES completion:NULL];

On the other hand, Apple's View Controller Programming Guide says:

When it comes time to dismiss a presented view controller, the preferred approach is to let the presenting view controller dismiss it. In other words, whenever possible, the same view controller that presented the view controller should also take responsibility for dismissing it. Although there are several techniques for notifying the presenting view controller that its presented view controller should be dismissed, the preferred technique is delegation.

This has led some answers here to suggest sticking with making a new protocol and delegation even when only a very simple view controller is being presented. Why is this the documentation's "preferred technique" as opposed to the single line above? Is there any offsetting advantages to downside of a large increase in code written with the delegate/protocol technique? Obviously if there is information from the presented view controller that needs to be passed back to the presenting view controller delegation is a good technique. However, the information is the reason for delegation, not simply cleanly removing the presented view controller from the screen.

2

2 Answers

3
votes

The same behavior could by achieved by [self dismissViewControllerAnimated:YES completion:nil] (before iOS 5 [self dismissModalViewControllerAnimated:YES]), as there's always at most one view controller presented (modally) at a time.

However, the point of the delegation pattern is that a single view controller could be presented in different ways such as modally or by being push to the navigation stack. That view controller doesn't know how it was presented (well, it could figure it out, but it should not care). The only thing it is supposed to do is to notify it's parent, i.e. the delegate, that its work is done. The delegate then decides how to remove the view controller (dismiss modal or pop from navigation stack etc.) or that the child should stay because the results of its work are insufficient. So the main idea is reusability of view controllers.

1
votes

[[self presentingViewController] dismissViewControllerAnimated:YES completion:NULL];

That may be the simplest, but it's often not very useful.

Modal views typically need to return some information to their caller; that's why they're modal. In more traditional SDKs modal windows block their caller until the modal window is dismissed. The result of the modal window is then returned to the caller. E.g.:

int result = ShowModalDialog("Do you want to continue?");
if (result == kYes) 
{
    doSomething();
}
else
{
    return;
}

In UIKit, -presentModalViewController: does not block, so you need some other mechanism for the modal view controller to return information to the presenting view controller. Typically that's done with delegation, though there are other ways (such as having the presenting controller handle the left and right UINavigationBar buttons).

If the modal view controller needs to return a value to its presenting view controller then that's done via delegation, and in that case it makes sense for the presenting controller to dismiss the modal controller after it has received the result. That's the original pattern.