Search code examples
iosswiftsegueinteractivetransition

Interactive Transition : Segue declaration


Theoretical question : in the code below, why, at the line of "performSegue....", the segue is not performed entirely ? I mean, how it know it's an interactive transition, and why the method "performSegue..." has not the same effect as if she was declared somewhere else ?

FirstViewController.swift

let transitionManager = TransitionManager()


override func viewDidLoad() {
    super.viewDidLoad()

    transitionManager.sourceViewController = self

    // Do any additional setup after loading the view.
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {

    let dest = segue.destinationViewController as UIViewController
    dest.transitioningDelegate = transitionManager
    transitionManager.destViewController = dest

}

Storyboard

The segue is from the FirstViewController to the SecondViewController.

  • Identifier : "segueIdentifier"

  • Segue : Modal

  • Destination : Current

TransitionManager.swift

class TransitionManager: UIPercentDrivenInteractiveTransition,UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate,UIViewControllerInteractiveTransitioning {

    var interactive = false
    var presenting = false

    var panGesture : UIPanGestureRecognizer!

    var sourceViewController : UIViewController! {
        didSet {

            panGesture = UIPanGestureRecognizer(target: self, action: "gestureHandler:")
            sourceViewController.view.addGestureRecognizer(panGesture)

        }
    }


    func gestureHandler(pan : UIPanGestureRecognizer) {

        let translation = pan.translationInView(pan.view!)

        let d =  translation.x / pan.view!.bounds.width * 0.5        

        switch pan.state {

        case UIGestureRecognizerState.Began :

            interactive = true

            sourceViewController.performSegueWithIdentifier("segueIdentifier", sender: self)


        case UIGestureRecognizerState.Changed :

            self.updateInteractiveTransition(d)

        default :

            interactive = false

            if d > 0.2 || velocity.x > 0 {
                self.finishInteractiveTransition()
            }
            else {
                self.cancelInteractiveTransition()
            }
        }

    }

    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {

        //Something....


        UIView.animateWithDuration(1.0, animations: {

            //Something....

            }, completion: {}

        })

    }

    func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
        return 1
    }

    // MARK: UIViewControllerTransitioningDelegate protocol methods

    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        self.presenting = true
        return self
    }

    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        self.presenting = false
        return self
    }

    func interactionControllerForPresentation(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        return self.interactive ? self : nil
    }

    func interactionControllerForDismissal(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        return self.interactive ? self : nil
    }





}

In fact, I have a lot of codes similar to this, this one is working but others very similar do precisely what I was explaining : the segue is just executed without interactive transition. Can someone explain me ?

Thanks for your help


Solution

  • If the problem is that your interactive transition animation is not being interactive, I'd suggest putting a breakpoint in interactionControllerForPresentation:

    • Make sure that the correct instance of interactionControllerForPresentation is called like you think it should be.

      For example, make sure that viewDidLoad of destination didn't replace the transitioningDelegate that you so carefully set in the prepareForSegue in the source controller ... this is easy to do if doing interactive transition from A to B and then again from B to C, what you set up in anticipation to B to C can interfere with what you intended to do from A to B.

    • Make sure that interactionControllerForPresentation is returning the value that you think it should (i.e. make sure that interactive is definitely true).

    Every time I've seen this behavior of a gesture not initiating the transition interactively, like I think it should, it has been because when interactionControllerForPresentation was called in the destination controller's transitioningDelegate, it didn't return a valid UIViewControllerInteractiveTransitioning (such as a UIPercentDrivenInteractiveTransition) like I intended it to.

    Anyway, you can diagnose this by adding a log statement in interactionControllerForPresentation, and you'll either see that (a) it's not called for some reason; or (b) self.interactive is not true.