iOS 7 use custom interactive transitions only some of the time

ios, ios7, objective-c

Solution

You should set NavigationController's interactivePopGestureRecognizer delegate to self and then handle its behavior in -gestureRecognizerShouldBegin:

That is, when you want the built-in pop gesture to fire, you must return YES from this method. The same goes for your custom gestures - you have to figure out which recognizer you are dealing with.

- (void)setup
{
    self.interactiveGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleTransitionGesture:)];
    self.interactiveGestureRecognizer.delegate = self;
    [self.navigationController.view addGestureRecognizer:self.interactiveGestureRecognizer];

    self.navigationController.interactivePopGestureRecognizer.delegate = self;
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    // Don't handle gestures if navigation controller is still animating a transition
    if ([self.navigationController.transitionCoordinator isAnimated])
        return NO;

    if (self.navigationController.viewControllers.count < 2)
        return NO;

    UIViewController *fromVC = self.navigationController.viewControllers[self.navigationController.viewControllers.count-1];
    UIViewController *toVC = self.navigationController.viewControllers[self.navigationController.viewControllers.count-2];

    if ([fromVC isKindOfClass:[ViewControllerB class]] && [toVC isKindOfClass:[ViewControllerA class]])
    {
        if (gestureRecognizer == self.interactiveGestureRecognizer)
            return YES;
    }
    else if (gestureRecognizer == self.navigationController.interactivePopGestureRecognizer)
    {
        return YES;
    }

    return NO;
}

You can check out a sample project for your scenario. Transitions between view controllers A and B are custom animated, with custom B->A pop gesture. Transitions between view controllers B and C are default, with built-in navigation controller's pop gesture.

Hope this helps!

Problem

So I have a UINavigationController, with Controller A as the root controller. When I want to push Controller B on top, I want to use a custom animated transition and a custom interactive transition. This works fine. When I want to push Controller C on top, I want to fall back to the default push/pop transitions that comes with UINavigationController. To make this happen I return nil for ``` navigationController:animationControllerForOperation:fromViewController:toViewController: ``` however if you return nil, then ``` navigationController:interactionControllerForAnimationController: ``` will never be called and the default "pan from left edge" pop interactive transition doesn't work. Is there a way to return the default push/pop animation controller and interaction controller? (Are there concrete implementations of `id<UIViewControllerAnimatedTransitioning>` and `id<UIViewControllerInteractiveTransitioning>`?) Or some other way?

Original source