ios - Cómo resolver el error "Error al determinar la dirección de navegación para desplazamiento"
iphone debugging (2)
Mi error más frecuente es "No se pudo determinar la dirección de navegación para el desplazamiento" por razones, ¿alguna idea sobre cómo podría resolverlo?
Aquí está la última excepción 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)
ACTUALIZACIÓN: finalmente logré reproducir el error en el simulador, es cuando toco una vista y, al mismo tiempo, la animación de desplazamiento UIPageViewController comienza programáticamente. Básicamente, si configuraViewViewControllers programmatically con la animación configurada en sí y la animación de desplazamiento. Si toca cualquier parte de la pantalla antes de que comience la animación de desplazamiento, se producirá el siguiente bloqueo *** Error de aserción en - [_ UIQueuingScrollView _didScrollWithAnimation: force:], /SourceCache/UIKit/UIKit-2372/_UIQueuingScrollView.m:778 como se describe aquí .
También descargué la aplicación de muestra PhotoScroller de Apple y la edité con un cambio de página programático y tienen el mismo error.
Mi solución no fue activar el cambio de página si el usuario está tocando actualmente la pantalla, también puede cambiar la animación para curvar o eliminar la animación.
Como mencioné en la actualización de la pregunta, UIPageViewController parece bloquearse en las siguientes condiciones al final de la animación de la página de cambios:
- Cambiar página programáticamente
- El cambio de página está animado
- TransitionStyle es igual a UIPageViewControllerTransitionStyleScroll
- El usuario está tocando la pantalla cuando comienza el cambio de página
Pude reproducir el error en la aplicación de muestra PhotoScroller de Apple, simplemente agregando un cambio de página programática. Entonces el error parece ser culpa de Apple.
Como no pude resolver el error, eliminé una de las condiciones que activan el error (esperando una mejor solución). No estaba bien con el uso de una transición curl (UIPageViewControllerTransitionStyleCurl) o la eliminación de la animación de transición. Ambas soluciones funcionan. Entonces, cuando el usuario está tocando la pantalla, no activa el cambio de página programática con la siguiente línea
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];
}
Con currentViewController.view es una subclase de UIView que implementa la siguiente propiedad en el encabezado
@property (nonatomic, assign) BOOL isBeingTouch;
y los siguientes métodos en 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;
}
Solo tengo botones como subvistas, por lo que funciona para la mayoría de los casos. Sin embargo, podría haber una solución más completa
Idealmente, nos gustaría saber si el UIScrollView
subyacente se está arrastrando o desacelerando. Pero Apple no permite el acceso público a UIScrollView
en el controlador de página, por lo que podemos realizar un seguimiento del estado de transición del controlador de la página con un BOOL a través de estos dos delegados.
- (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;
}
}
En su código para hacer una transición programática de las vistas de página, solo proceda si el controlador de página no está en transición.
if (!self.isTransitioning) {
[self.pageController setViewControllers:@[toViewController]
direction:UIPageViewControllerNavigationDirectionForward
animated:YES
completion:nil];
}