jjatie jjatie - 1 year ago 63
Swift Question

Losing reference to transitioningDelegate before presetentation presentation

I had a working custom UIPresentationController prior to Xcode beta 2 and iOS 10 beta 2. I haven't changed any code, but the presentation is now being presented with the standard modal presentation.

There is a note in the Apple sample code for UIPresentationController that says:

For presentations which will use a custom presentation controller,
it is possible for that presentation controller to also be the
transitioningDelegate. This avoids introducing another object or
implementing in the source
view controller.

transitioningDelegate does not hold a strong reference to its destination object.To prevent presentationController from being
released prior to calling -presentViewController:animated:completion:
the NS_VALID_UNTIL_END_OF_SCOPE attribute is appended to the

I've checked the transitioningDelegate on the presented view controller before and after the presentation. Before it is my custom UIPresentationController, but after it is nil. My guess is that the reference is being released, but I cannot find an equivalent to NS_VALID_UNTIL_END_OF_SCOPE in Swift. EDIT: I've verified that transitioningDelegate is set up until just before the presentation, and then is nil when it is time to present.

My code in the presenting view controller:

@IBAction func buttonAction(_ sender: UIButton) {
let secondViewController = storyboard!.instantiateViewController(withIdentifier: "NewViewController") as! NewViewController
let presentationController = MyPresentationController(presentedViewController: secondViewController, presenting: self)
presentationController.initialFrame = button.frame
secondViewController.transitioningDelegate = presentationController

// Move map
let pixelsToMove: CGFloat = mapView.frame.height / 4
let region = self.mapView.region

self.mapView.setRegion(region, offsetBy: pixelsToMove, animated: true)

// Delegate to NewViewController
secondViewController.mapView = mapView
mapView.delegate = secondViewController

UIView.animate(withDuration: 0.3, animations: {
let tabBar = self.tabBarController!.tabBar
tabBar.frame.origin.y += tabBar.frame.height

self.present(secondViewController, animated: true, completion: nil)

And my code in the UIPresentationController:

override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
presentedViewController.modalPresentationStyle = .custom

Answer Source

The problem was in beta 2 the method signatures inUIViewControllerTransitioningDelegate changed, and so they were not being called in my code. I don't understand why, but once again everything works perfect without explicitly storing a strong reference to the presentation controller.