In iOS 13, viewWillAppear is not called when dismissing view controller. As a workaround, it is mentioned to override UIAdaptivePresentationControllerDelegate delegate, but it's not working for me. What am I doing wrong?
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "MyVC" {
let destination = segue.destination as! MyViewController
destination.presentationController?.delegate = self
}
}
And then,
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
resumePipeline() //<--Does not get called
}
What am I doing wrong?
You're probably assuming that presentationControllerDidDismiss is always called when the dismissal takes place. That's a false assumption. It is called when the user drags down on the presented view to dismiss it.
You need to think of the presented view controller as if it were a popover. It isn't completely replacing the presenting view controller's view; it just covers it partially. So there is no viewDidAppear call, because the main view never disappeared.
Either you need to go back to forcing your presented view controller to be fullScreen or you need to adapt your architecture to work with the new style of presented view controller.
Related
I have a container view in my Storyboard that displays another view controller that I already programmed and stuff. I want to communicate between the main View Controller and the contained-view controller. I know how to use delegates and I am comfortable with using them, however I normally set up delegates when I initialize a ViewController, however in this case I don't know where to apply this, since the view controller is already there per the storyboard. Normally I would do something like this:
class HomeVC: UIViewController {
func initializeVC() {
resultsVC = self.storyboard?.instantiateViewController(withIdentifier: "resultsView") as! GoalsVC
resultsVC.calcDelegate = self //I set the "HomeVC" as the Delegate since it has all the functions I need
}
}
As mentioned above, since I never really created this view controller via code, I don't know how to assign a delegate (specially setting the delegate to "self" (where Self is the main View Controller)
You can assign delegate in prepareforsegue. Like below code
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "container_segue") {
let controller = segue.destination as! containerController
controller.delegate = self
}
}
When project runs, this method called automatically because we had created segue in the storyboard.
By using segue.identifier you can check for which controller segue is going to happen and accordingly you can achieve your requirement.
As you are using storyboard for container view. There is a segue with embed type. Give this segue a identifier, say MyContainedViewControllerSegueId
Then in prepare(for segue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "MyContainedViewControllerSegueId" {
// here you get your contained view controller as `segue.destination`
// cast it your subclassed view controller
// use delegate on that subclassed view controller for communication purpose.
}
}
I am trying to implement a popover whose anchor is a bar button item for my iphone app. I have connected the bar button item to the view controller via a segue pathway configured as show as "present as popover." I have also set my own size for the view controller and selected "use preferred explicit size." Based on previous posts about this similar topic, I have implemented the following code for my popover. However, the popover is still covering the entire screen, probably because my adaptivePresentationStyle method is not being called ("hello" does not print to the screen). Note that I have also implemented the UIPopoverPresentationControllerDelegate. Where did I go wrong?
override func prepare (for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "popoverLogin" {
let popoverViewController = segue.destination
popoverViewController.modalPresentationStyle = UIModalPresentationStyle.popover
popoverViewController.popoverPresentationController!.delegate = self }
}
// MARK: - UIPopoverPresentationControllerDelegate method
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
// Force popover style
print ("hello")
return UIModalPresentationStyle.none
}
Thanks!
In my case your code works and popover is presented normally!
Make sure your segue has the right "Kind": "Present As Popover".
I have been working with modal view controllers for a while now but I was wondering whether or not there is a function to call to let the underlying view controller know that a modal view controller that has been overlaying it has been dismissed.
If that is possible, how can you tell in a view controller that a modal view has been dismissed so that e.g. another modal view controller can be opened right after the old one has been dismissed?
Thanks in advance
This can be easily done using delegation.
Create a protocol in the modal view controller class(the view controller that is being presented).
protocol ModalViewControllerDelegate:class {
func dismissed()
}
Also create a delegate property and call the delegate method when the modal view controller is dismissed, say on tap of a button. Here is some code to help you with that.
class ModalViewController1: UIViewController {
var delegate:ModalViewControllerDelegate?
#IBAction func back(_ sender: Any) {
delegate?.dismissed()
}
}
Now in the presenting view controllers's prepare for segue method, make the presenting view controller as the delegate of the presented modal view controller. Heres some code.
import UIKit
class ViewController: UIViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "modal1" {
if let modalVC1 = segue.destination as? ModalViewController1 {
modalVC1.delegate = self
}
}
}
}
extension ViewController: ModalViewControllerDelegate {
func dismissed() {
dismiss(animated: true, completion: nil)//dismiss the presented view controller
//do whatever you want after it is dismissed
//like opening another modal view controller
}
}
The dismissed function will be called after the modal view controller's back button is tapped and you can dismiss the presented view controller and also proceed with whatever you want to do after that.
I have a popover that is using the same view controller that calls it.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "groupSelect" {
let popVC = segue.destination
popVC.popoverPresentationController?.delegate = self
}
}
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return UIModalPresentationStyle.none
}
However, because I used the storyboard to make everything, I'm not really sure how or where I can take over or add code when the popover gets dismissed. In Xcode 8.2 with Swift 3, adding a popover with the storyboard editor automatically makes the popover dismiss when the user touches outside the popover. Everything is working great, the only problem is that when I return from the popover, the table under it won't have the reload function called so any changes made in the popover don't take effect for the user.
Implement UIPopoverPresentationControllerDelegate method popoverPresentationControllerDidDismissPopover which tells the delegate that the popover was dismissed.
I'm updating an app to use universal storyboards. I've created a popover segue to a new viewcontroller using interface builder by dragging from a button to my new viewcontroller and selecting 'Present As Popover' as the kind of segue.
When the user presses outside of the popover (dismissing it) I need to be notified in the presenting view controller so I can undo their actions. How can I do this?
Normally I would have created the popover manually and made my viewcontroller the popover's delegate; allowing me to use the popoverControllerDidDismissPopover delegate call back. However, this is deprecated in iOS9 and even if it wasn't I've no idea where to find the popover so I can set its delegate to my view controller.
Not sure which method you're referring to as being deprecated but you can still use the UIPopoverPresentationControllerDelegate to achieve this. Something like:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "popoverSegue" {
let vc = segue.destinationViewController
sortVC.modalPresentationStyle = .Popover
sortVC.popoverPresentationController?.sourceRect = filterButton.bounds
sortVC.preferredContentSize = CGSizeMake(216, 150)
sortVC.popoverPresentationController!.delegate = self
}
}
And then use the
func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController)
method to handle its dismissal.
The popoverControllerDidDismissPopover: method has been replaced by popoverPresentationControllerShouldDismissPopover: because UIPopoverControllerDelegate has been replaced by the UIPopoverPresentationControllerDelegate.
From your presenting view controller, conform to the new protocol and set the delegate for the popover presentation controller in prepareForSegue::
class MyPresentingViewController: UIViewController, UIPopoverPresentationControllerDelegate {
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let popoverPresentationController = segue.destinationViewController.popoverPresentationController {
popoverPresentationController.delegate = self
}
}
func popoverPresentationControllerShouldDismissPopover(popoverPresentationController: UIPopoverPresentationController) -> Bool {
return true
}
}
You can then use the delegate method to handle detection of the dismissal in the way that you were previously intending.
The updated answer for this issue.
All credit to this answer:
The method you must use on iOS 13:
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
The UIPopoverPresentationControllerDelegate inherits from UIAdaptivePresentationControllerDelegate which contains the presentationControllerShouldDismiss and presentationControllerDidDismiss as Beto points out.
I simply moved the code I had in the popover versions of these functions to UIAdaptivePresentationControllerDelegate version and they work exactly the same as before.
Did not have to change the delegate declarations on the view controller or set isModalInPresentation.
The original code still worked under 13.2.3 but those function are depreciated and one day they will stop working...or not?
my app is an iPad app using popovers and not presentation sheets or card styles.