Alfie Hanssen Alfie Hanssen - 8 days ago 4
iOS Question

Proper way to implement a custom UIViewController interactive transition using UIViewControllerInteractiveTransitioning Delegate Protocol

I'm interested in a concise example of how to create an

NSObject
subclass that implements the
UIViewControllerInteractiveTransitioning
protocol to manage a custom interactive transition between two
UIViewController
s. Ideally in response to a swipe gesture. Something akin to the iOS7 default interactive swipe that now comes with
UINavigationController
, but a custom/manual implementation example of this.

I've read the docs:



And looked at a few examples elsewhere:


  • one

  • two

  • three

  • four (I set this up but it's more about
    UIViewController
    containment
    and manual implementation of these transitions rather than
    UIViewControllerInteractiveTransitioning



The docs are fairly clear but dont reference sample code. And the examples leave a little to be desired (unanswered questions about how the various pieces are tied together).

So my questions are:


  1. Can someone help fill in the blanks about how to tie a gesture (e.g. a swipe) to the object that implements the
    UIViewControllerInteractiveTransitioning
    protocol?

  2. What is the relationship between object implementing the UIViewControllerInteractiveTransitioning protocol and that implementing the UIViewControllerAnimatedTransitioning protocol? Seems like you must have both to trigger interactive transitions...



Thanks in advance...

Answer

1) The easiest way to tie a gesture to the UIViewControllerInteractiveTransitioning object, is making it subclass of UIPercentDrivenInteractiveTransition. Then where you implement the gesture handler, you call updateInteractiveTransition: here an example with code:

-(void)handlePinch:(UIPinchGestureRecognizer *)pinch {

    CGFloat scale = pinch.scale;
    switch (pinch.state) {
      case UIGestureRecognizerStateBegan: {
          _startScale = scale;
          self.interactive = YES;
          [self.navigationController popViewControllerAnimated:YES];
          break;
      }
      case UIGestureRecognizerStateChanged: {
          CGFloat percent = (1.0 - scale/_startScale);
          [self updateInteractiveTransition:(percent < 0.0) ? 0.0 : percent];
          break;
      }
      case UIGestureRecognizerStateEnded: {
          CGFloat percent = (1.0 - scale/_startScale);
          BOOL cancelled = ([pinch velocity] < 5.0 && percent <= 0.3);
          if (cancelled) [self cancelInteractiveTransition];
          else [self finishInteractiveTransition];
          break;
      }
      case UIGestureRecognizerStateCancelled: {
          CGFloat percent = (1.0 - scale/_startScale);
          BOOL cancelled = ([pinch velocity] < 5.0 && percent <= 0.3);
          if (cancelled) [self cancelInteractiveTransition];
          else [self finishInteractiveTransition];
          break;
      }
    }
}

This code is from https://www.captechconsulting.com/blogs/ios-7-tutorial-series-custom-navigation-transitions--more

2) The function animateTransition of UIViewControllerAnimatedTransitioning is used to perform the interactive transition. It is automatically partitioned in "keyframes" thanks to your previous call to updateInteractiveTransition. But I suppose that if you implement your startInteractiveTransition: method of UIViewControllerInteractiveTransitioning (so without using UIPercentDrivenInteractiveTransition subclass) then you are responsible to manage the fully transition (not sure about that.. sorry but the documentation in my opinion is not really clear).