如何解决“无法确定滚动的导航方向”错误

我最常见的错误是“无法确定滚动的导航方向”,原因是什么,我是如何解决它的?

这是最后一个Exception Backtrace:

1. CoreFoundation __exceptionPreprocess + 131 2. libobjc.A.dylib _objc_exception_throw + 39 3. CoreFoundation +[NSException raise:format:] + 1 4. Foundation -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 91 5. UIKit __54-[_UIQueuingScrollView _didScrollWithAnimation:force:]_block_invoke + 221 6. UIKit -[_UIQueuingScrollView _didScrollWithAnimation:force:] + 567 7. UIKit -[_UIQueuingScrollView _scrollViewAnimationEnded:finished:] + 73 8. UIKit -[UIAnimator stopAnimation:] + 471 9. UIKit -[UIAnimator(Static) _advanceAnimationsOfType:withTimestamp:] + 285 10. UIKit -[UIAnimator(Static) _LCDHeartbeatCallback:] + 53 11. QuartzCore CA::Display::DisplayLinkItem::dispatch() + 99 12. QuartzCore CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 345 13. IOMobileFramebuffer IOMobileFramebufferVsyncNotifyFunc + 105 14. IOKit _IODispatchCalloutFromCFMessage + 249 15. CoreFoundation __CFMachPortPerform + 137 16. CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 35 17. CoreFoundation __CFRunLoopDoSource1 + 347 18. CoreFoundation __CFRunLoopRun + 1399 19. CoreFoundation _CFRunLoopRunSpecific + 523 20. CoreFoundation _CFRunLoopRunInMode + 107 21. GraphicsServices _GSEventRunModal + 139 22. UIKit _UIApplicationMain + 1137 23. MyApp main (main.m:13) 

更新:我终于设法重现模拟器上的错误,当我触摸视图时,同时,UIPageViewController滚动动画以编程方式启动。 基本上,如果以编程方式设置ViewsControllers,并将动画设置为yes并滚动动画。 如果您在滚动动画开始之前触摸屏幕的任何部分,则会出现以下崩溃*** – 断言失败 – [_ UIQueuingScrollView _didScrollWithAnimation:force:],/ SourceCache / UIKit / UIKit-2372 / _UIQueuingScrollView.m:778如此处所述。

我还下载了Apple的PhotoScroller示例应用程序,并通过程序化页面更改对其进行了编辑,它们也有相同的错误。

我的解决方案是,如果用户当前正在触摸屏幕,则不会触发页面更改,您还可以将动画更改为curl或删除动画。

理想情况下,我们想知道底层UIScrollView是否被拖动或减速。 但Apple不允许公共访问页面控制器中的UIScrollView ,因此我们可以通过这两个代表跟踪BOOL的页面控制器转换状态。

 - (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; } } 

在以编程方式转换页面视图的代码中,仅在页面控制器尚未转换时才继续。

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

正如我在问题更新中提到的,UIPageViewController似乎在更改页面动画结束时在以下条件下崩溃:

  • 以编程方式更改页面
  • 页面更改是动画的
  • TransitionStyle等于UIPageViewControllerTransitionStyleScroll
  • 用户在页面更改开始时触摸屏幕

我能够通过添加程序化页面更改来重现Apple的PhotoScroller示例应用程序中的错误。 所以这个错误似乎是Apple的错。

由于我无法解决错误,我删除了触发错误的条件之一(等待更好的解决方案)。 我没有使用curl过渡(UIPageViewControllerTransitionStyleCurl)或删除过渡动画。 这些解决方案都有效。 因此,当用户触摸屏幕时,我不会使用以下行触发程序化页面更改

 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]; } 

currentViewController.view是UIView的子类,在头文件中实现以下属性

 @property (nonatomic, assign) BOOL isBeingTouch; 

以及主要的以下方法

 - (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; } 

我只是将按钮作为子视图,因此适用于大多数情况。 但是,可能有更完整的解决方案