Подтвердить что ты не робот

Как решить ошибку "Не удалось определить направление навигации для прокрутки"

Моя самая частая ошибка: "Не удалось определить направление навигации для прокрутки" по какой-либо причине, любое представление о том, как я могу ее решить?

Вот последняя обратная трассировка исключения:

 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 и отредактировал его с программным изменением страницы, и у них такая же ошибка.

Мое решение состояло не в том, чтобы вызвать изменение страницы, если пользователь в данный момент касается экрана, вы также можете изменить анимацию для завивки или удаления анимации.

4b9b3361

Ответ 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;
}

У меня просто кнопки в качестве подзонов, поэтому он работает для большинства случаев. Однако может быть более полное решение