Xcode 8 Swift 3: Modal presentation transitioning delegate not called
Asked Answered
S

2

8

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
Slough answered 14/9, 2016 at 18:58 Comment(0)
S
34

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
}
Slough answered 15/9, 2016 at 14:7 Comment(2)
I've been stumped on a similar problem for hours... In my case, the two "animationController" functions get called, but not the "presentationController" function. The modalPresentationStyle is .custom. Help! This is driving me completely insane! ;-)Zweig
Okay, figured it out... There's actually another version of public func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? that I copied from some example code. Can't recall the exact wording, but the compiler didn't recognize the error.Zweig
U
3

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
Unfamiliar answered 11/1, 2019 at 14:31 Comment(1)
Adding the transitionDelegate to the inits fixed my issue, but I used .custom for the presentation style in order for the presentationController(..) method to work.Pinto

© 2022 - 2024 — McMap. All rights reserved.