Как решить ошибку "Не удалось определить направление навигации для прокрутки"
Моя самая частая ошибка: "Не удалось определить направление навигации для прокрутки" по какой-либо причине, любое представление о том, как я могу ее решить?
Вот последняя обратная трассировка исключения:
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 запускается программно. В принципе, если программно настроить setViewsControllers с анимацией, установленной в yes и прокруткой анимации. Если вы касаетесь какой-либо части экрана до начала анимации прокрутки, произойдет следующий сбой *** Ошибка утверждения в - [_ UIQueuingScrollView_didScrollWithAnimation: force:],/SourceCache/UIKit/UIKit-2372/_UIQueuingScrollView.m:778 как описано здесь.
Я также загрузил пример приложения Apple PhotoScroller и отредактировал его с программным изменением страницы, и у них такая же ошибка.
Мое решение состояло не в том, чтобы вызвать изменение страницы, если пользователь в данный момент касается экрана, вы также можете изменить анимацию для завивки или удаления анимации.
Ответы
Ответ 1
В идеале мы хотели бы знать, перетаскивается ли базовый 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];
}
Ответ 2
Как я упоминал в обновлении вопроса, 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;
}
У меня просто кнопки в качестве подзонов, поэтому он работает для большинства случаев. Однако может быть более полное решение