How to solve “Failed to determine navigation direction for scroll” bug

血红的双手。 提交于 2019-11-30 01:33:22

Ideally we would want to know whether the underlying UIScrollView is being dragged or decelerating. But Apple doesn't allow public access to the UIScrollView in the page controller, so we can keep track of the page controller's transition state with a BOOL via these two delegates.

- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers
{
    self.transitioning = YES;
}

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
    if (finished) {
        self.transitioning = NO;
    }
}

In your code to programmatically transition the page views, only proceed if the page controller isn't already transitioning.

if (!self.isTransitioning) {
    [self.pageController setViewControllers:@[toViewController]
                                  direction:UIPageViewControllerNavigationDirectionForward
                                   animated:YES
                                 completion:nil];
}

As I mention in the question update, UIPageViewController seems to crash in the following conditions at the end of the change page animation:

  • Change page programmatically
  • Page change is animated
  • TransitionStyle is equal to UIPageViewControllerTransitionStyleScroll
  • User is touching the screen when the page change starts

I was able to reproduce the bug in Apple's PhotoScroller sample app, just by adding a programmatic page change. So the bug seems to be Apple's fault.

As I wasn't able to solve the bug, I remove one of the condition that trigger the bug (waiting for a better solution). I wasn't ok with using a curl transition (UIPageViewControllerTransitionStyleCurl) or removing the transition animation. Both these solutions work. So, when user is touching the screen I don't trigger the programmatic page change with the following line

UIViewController* currentViewController = [self.viewControllers objectAtIndex:0];
if(currentViewController.view.isBeingTouch){
        ContentViewController *nextViewController = [[ContentViewController alloc] init];
        NSArray *viewControllers =;
        [self setViewControllers: @[loadingController] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
}

With currentViewController.view being a subclass of UIView implementing the following property in header

@property (nonatomic, assign) BOOL isBeingTouch;

and the following methods in main

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    _isBeingTouch = YES;
    [super touchesBegan:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
    _isBeingTouch = NO;
    [super touchesCancelled:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    _isBeingTouch = NO;
    [super touchesEnded:touches withEvent:event];
}

-(BOOL)isBeingTouch{

    for (UIView * view in self.subviews){
        if([view isKindOfClass:[UIButton class]]) {
            UIButton * b = (UIButton *) view;
            if(b.isHighlighted)
                return YES;
        }
    }

    return _isBeingTouch;
}

I just have buttons as subviews, so it works for most of the cases. However, there might a more complete solution

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!