Exception de paramètre non valide levée par _UIQueuingScrollView

Mon application qui contient un UITableViewController embedded dans UIPageViewController triggers cette exception de time en time:

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 

Est-ce que quelqu'un a déjà vu cela ou a une idée de ce que la raison pourrait être?

Edit: après avoir utilisé ce correctif pour plus de time, je peux toujours voir le bug à l'occasion donc ce n'est pas le correctif complet (enfin … c'était toujours un peu un hack). Je mettrai à jour avec la solution réelle une fois que je le findai.


J'ai rencontré cette même erreur en utilisant UIPageViewController. Après des heures de debugging du problème, j'ai découvert que la cause était l'utilisation d'animations UIView dans le gestionnaire de complétion de setViewControllers de UIPageViewController: direction: animated: completion :.

Je ne sais pas pourquoi l'animation à ce stade provoque l'erreur d'assertion (je n'animais pas UIPageViewController ou ses controllers de vue enfant), mais envelopper le bloc de code avec dispatch_async sur la queue principale résout le problème et arrête le plantage.

J'ai vu ce plantage lors d'une tentative de transition vers une nouvelle page par programmation. Une réponse qui a du sens pour moi est de ne pas leur permettre de toucher la page vue pendant la transition.

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

Assurez-vous simplement que vous ne faites aucune animation dans viewDidAppear dans le controller vers lequel vous revenez. Ou si vous devez le faire après un certain time une fois que la vue est apparue.

J'ai rencontré la même erreur avec un UIViewController que j'avais embedded dans un UIPageViewController. Dans mon cas, j'ai réalisé que mon controller enfant avait remplacé viewWillAppear et viewDidAppear sans appeler super . Bien que je ne peux que deviner les détails, il est logique que cela puisse gâcher la gestion des vues. L'ajout des super appels a fait disparaître le problème.

Dans mon cas, le problème était dans l'implémentation de UIPageViewControllerDelegate :

Je mets à jour les contraintes dans pageViewController(_ pageViewController:, didFinishAnimating:, previousViewControllers:, transitionCompleted:)

dispatch_async sur la queue principale résoudre ce problème

J'utilise UIPageViewController avec des points. Après que l'user a balayé les points, le délégué didFinishAnimating est appelé et je triggers une autre animation, puis il plante. Mais cela n'arrive que lorsque l'user balaie les points.

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