Issue
The delegate functions within 'DrinkTransitioningDelegate' are not called. The 'td' instance remains in memory during and beyond the lifecycle of the presentation.
class PresentingViewController: UIViewController {
let td = DrinkTransitioningDelegate()
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = inventory.beverages[indexPath.row]
item.isSelected = true
let controller = DrinkViewController(item: item)
controller.delegate = self
controller.transitioningDelegate = td
controller.modalPresentationStyle = .custom
//let navCon = UINavigationController(rootViewController: controller)
//navCon.transitioningDelegate = td
//navCon.modalPresentationStyle = .custom
present(controller, animated: true)
}
}
class DrinkTransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {
func presentationControllerForPresentedViewController(presented: UIViewController, presentingViewController presenting: UIViewController!, sourceViewController source: UIViewController) -> UIPresentationController? {
return DrinkPresentationViewController(presentedViewController:presented, presenting: presenting)
}
let animationController = DrinkAnimatedTransition()
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
animationController.isPresentation = true
return animationController
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
animationController.isPresentation = false
return animationController
}
deinit {
print("adf")
}
}
History
- The question was raised for iOS 7 here
- The question was raised for iOS 9 here
Solution
Optional protocol functions are now a thing.
The delegate is comprised completely of optional functions, so there were no warnings.
These functions appeared to the compiler as my own custom functions.
func presentationControllerForPresentedViewController(presented: UIViewController, presentingViewController presenting: UIViewController!, sourceViewController source: UIViewController) -> UIPresentationController? {
return DrinkPresentationViewController(presentedViewController:presented, presenting: presenting)
}
let animationController = DrinkAnimatedTransition()
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
animationController.isPresentation = true
return animationController
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
animationController.isPresentation = false
return animationController
}
These are the correct functions.
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return DrinkPresentationViewController(presentedViewController:presented, presenting: presenting)
}
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let animationController = DrinkAnimatedTransition()
animationController.isPresentation = true
return animationController
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let animationController = DrinkAnimatedTransition()
animationController.isPresentation = false
return animationController
}
Your transitioningDelegate = self may not be called early enough. The solution around my issue was to add the following, then both animationController(forPresented..) and animationController(forDismissed..) we're called.
init() {
super.init(nibName: nil, bundle: nil)
modalPresentationStyle = .overCurrentContext
transitioningDelegate = self
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
modalPresentationStyle = .overCurrentContext
transitioningDelegate = self
}
You may not need the following line, but left in here in many cases if you have a partial half drawer screen.
modalPresentationStyle = .overCurrentContext