La exception de parámetro inválida lanzada por _UIQueuingScrollView

Mi aplicación que contiene un UITableViewController embedded en UIPageViewController genera esta exception de vez en cuando:

Invalid parameter not satisfying: [views count] == 3 

Backtrace:

 * thread #1: tid = 0x6239fa, 0x03d1d88a libobjc.A.dylib`objc_exception_throw, queue = 'com.apple.main-thread, stop reason = breakpoint 25.3 frame #0: 0x03d1d88a libobjc.A.dylib`objc_exception_throw frame #1: 0x0404f448 CoreFoundation`+[NSException raise:format:arguments:] + 136 frame #2: 0x03428fee Foundation`-[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116 frame #3: 0x01e7c535 UIKit`-[_UIQueuingScrollView _replaceViews:updatingContents:adjustContentInsets:animated:] + 185 frame #4: 0x01e800ca UIKit`-[_UIQueuingScrollView _didScrollWithAnimation:force:] + 1231 frame #5: 0x01e7bb57 UIKit`-[_UIQueuingScrollView _scrollViewAnimationEnded:finished:] + 104 frame #6: 0x0190583c UIKit`-[UIScrollView(UIScrollViewInternal) animator:stopAnimation:fraction:] + 62 frame #7: 0x0197096e UIKit`-[UIAnimator stopAnimation:] + 533 frame #8: 0x0197100a UIKit`-[UIAnimator(Static) _advanceAnimationsOfType:withTimestamp:] + 325 frame #9: 0x01970b76 UIKit`-[UIAnimator(Static) _LCDHeartbeatCallback:] + 67 frame #10: 0x01663b8a QuartzCore`CA::Display::DisplayLinkItem::dispatch() + 48 frame #11: 0x01663a46 QuartzCore`CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 310 frame #12: 0x01663f6b QuartzCore`CA::Display::TimerDisplayLink::callback(__CFRunLoopTimer*, void*) + 123 frame #13: 0x0400dbd6 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22 frame #14: 0x0400d5bd CoreFoundation`__CFRunLoopDoTimer + 1181 frame #15: 0x03ff5628 CoreFoundation`__CFRunLoopRun + 1816 frame #16: 0x03ff4ac3 CoreFoundation`CFRunLoopRunSpecific + 467 frame #17: 0x03ff48db CoreFoundation`CFRunLoopRunInMode + 123 frame #18: 0x0533b9e2 GraphicsServices`GSEventRunModal + 192 frame #19: 0x0533b809 GraphicsServices`GSEventRun + 104 frame #20: 0x01874d3b UIKit`UIApplicationMain + 1225 

¿Alguien ha visto esto o tiene una idea de cuál podría ser la razón?

Editar: después de usar esta corrección por más time, todavía puedo ver el error de vez en cuando, así que esta no es la solución completa (bueno … siempre fue como un hack). Voy a actualizar con la solución real una vez que la encuentre.


He encontrado este mismo error usando UIPageViewController. Después de horas depurando el problema, descubrí que la causa era usar animaciones UIView dentro del manejador de finalización de setViewControllers de UIPageViewController: direction: animated: completion :.

No sé por qué animar en esa etapa provoca el error de aserción (no estaba animando UIPageViewController ni sus controlleres de vista secundarios), pero envolver el bloque de códigos con dispatch_async en la queue principal resuelve el problema y detener el locking.

Vi este locking al intentar la transición programática a una nueva página. Una respuesta que tenía sentido para mí es no permitirles tocar la vista de página durante la transición.

 __block UIView *pageView = pageViewController.view; // Disable page view to not allow the user to interrupt the page view animation and cause crash pageView.userInteractionEnabled = NO; [pageViewController setViewControllers:@[viewController] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:^(BOOL finished) { if (finished) { pageView.userInteractionEnabled = YES; // re-enable } }]; 

Solo asegúrate de que no estás haciendo ninguna animation dentro de viewDidAppear en el controller al que volverás. O si tiene que hacerlo después de un poco de retraso una vez que haya aparecido la vista.

Encontré el mismo error con un UIViewController que había embedded en un UIPageViewController. En mi caso, me di count de que mi controller secundario había anulado la viewWillAppear y viewDidAppear sin llamar a super . Aunque solo puedo adivinar los detalles, tiene sentido que hacerlo podría dañar la administración de la vista. Al agregar las super llamadas, el problema desapareció.

En mi caso, el problema estaba en la implementación de UIPageViewControllerDelegate :

Actualizo las restricciones en pageViewController(_ pageViewController:, didFinishAnimating:, previousViewControllers:, transitionCompleted:)

dispatch_async en queue principal resuelve este problema

Utilizo UIPageViewController con puntos. Después de que el usuario pulsa los puntos, el delegado didFinishAnimating recibe una llamada y yo active otra animation, luego se bloquea. Pero solo sucede cuando el usuario desliza los puntos.

 - (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers transitionCompleted:(BOOL)completed { if (completed && finished) { dispatch_async(dispatch_get_main_queue(), ^{ [self animateSomeView]; }) } }