Dismissing a Presented View Controller
I have a theoretic question. Now İ'm reading Apple's ViewController guide.
They wrote:
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.
But I can't explain, why I have to create a protocol in presented VC and add delegate varible, create delegate method in presenting VC for dismissing presented VC, instead of a simple call in presented view controller method
[self dismissViewControllerAnimated:NO completion:nil]
?
Why is the first choice better? Why does Apple recommend it?
I think Apple are covering their backs a little here for a potentially kludgy piece of API.
[self dismissViewControllerAnimated:NO completion:nil]
Is actually a bit of a fiddle. Although you can - legitimately - call this on the presented view controller, all it does is forward the message on to the presenting view controller. If you want to do anything over and above just dismissing the VC, you will need to know this, and you need to treat it much the same way as a delegate method - as that's pretty much what it is, a baked-in somewhat inflexible delegate method.
Perhaps they've come across loads of bad code by people not really understanding how this is put together, hence their caution.
But of course, if all you need to do is dismiss the thing, go ahead.
My own approach is a compromise, at least it reminds me what is going on:
[[self presentingViewController] dismissViewControllerAnimated:NO completion:nil]
[Swift]
self.presentingViewController?.dismiss(animated: false, completion:nil)
Updated for Swift 3
I came here just wanting to dismiss the current (presented) View Controller. I'm making this answer for anyone coming here with the same purpose.
Navigation Controller
If you are using a navigation controller, then it is quite easy.
Go back to the previous view controller:
// Swift
self.navigationController?.popViewController(animated: true)
// Objective-C
[self.navigationController popViewControllerAnimated:YES];
Go back to the root view controller:
// Swift
self.navigationController?.popToRootViewController(animated: true)
// Objective-C
[self.navigationController popToRootViewControllerAnimated:YES];
(Thanks to this answer for the Objective-C.)
Modal View Controller
When a View Controller is presented modally, you can dismiss it (from the second view controller) by calling
// Swift
self.dismiss(animated: true, completion: nil)
// Objective-C
[self dismissViewControllerAnimated:YES completion:nil];
The documentation says,
The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, UIKit asks the presenting view controller to handle the dismissal.
So it works for the presented view controller to call it on itself. Here is a full example.
Delegates
The OP's question was about the complexity of using delegates to dismiss a view.
- This Objective-C answer goes into it quite a bit.
- Here is a Swift example.
To this point I have not needed to use delegates since I usually have a navigation controller or modal view controllers, but if I do need to use the delegate pattern in the future, I will add an update.
This is for view controller reusability.
Your view controller shouldn't care if it is being presented as a modal, pushed on a navigation controller, or whatever. If your view controller dismisses itself, then you're assuming it is being presented modally. You won't be able to push that view controller onto a navigation controller.
By implementing a protocol, you let the parent view controller decide how it should be presented/pushed and dismissed/popped.
try this:
[self dismissViewControllerAnimated:true completion:nil];
In my experience, it comes in handy when you need to dismiss it from any ViewController you want and perform different tasks for each viewcontroller that dismisses it. Any viewController that adopts the protocol can dismiss the view in it's own way. (ipad vs iphone, or passing different data when dismissing from different views, calling different methods when dismissing, etc..)
Edit:
So, to clarify, if all you ever want to do is dismiss the view, I see no need to setup the delegate protocol. If you need to do different things after you dismiss it from different presenting view controllers, It would be your best way to go using the delegate.