Question

My app that contains a UITableViewController embedded in UIPageViewController raises this exception from time to 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

Does anyone have seen this already or have an idea what the reason could be?

Was it helpful?

Solution

Edit: after using this fix for more time, I can still see the bug on occasion so this isn't the complete fix (well... it was always kind of a hack). I'll update with the actual solution once I'll find it.


I've encountered this same error using UIPageViewController. After hours debugging the issue, I've found the cause was using UIView animations inside the completion handler of UIPageViewController's setViewControllers:direction:animated:completion:.

I don't know why animating at that stage causes the assertion error (I wasn't animating the UIPageViewController or its child view controllers), but wrapping the code block with dispatch_async on the main queue solves the issue and stop the crashing.

OTHER TIPS

I saw this crash when trying to programmatically transition to a new page. An answer that made sense to me is to not allow them to touch the page view during the 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
    }
}];

Just make sure you are not doing any animations within viewDidAppear in the controller that you are going back to. Or if you have to do it after some delay once the view has appeared.

I use UIPageViewController with Dots. After user swipes on the dots, the delegate didFinishAnimating get called and I trigger other animation, then it crashes. But it only happen when user swipes on the dots.

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

I encountered the same error with a UIViewController I had embedded in a UIPageViewController. In my case, I realized that my child controller had overridden viewWillAppear and viewDidAppear without calling through to super. Although I can only guess at the details, it makes sense that doing so could mess up the view management. Adding the super calls in made the problem go away.

In my case problem was in implementation of UIPageViewControllerDelegate:

I update constraints in pageViewController(_ pageViewController:, didFinishAnimating:, previousViewControllers:, transitionCompleted:)

dispatch_async on main queue resolve this problem

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top