23

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?

Ortwin Gentz
  • 52,648
  • 24
  • 135
  • 213
  • After running into this problem, the best solution I found was to do myself the animation `UIView transitionWithView:toView:..`. I think it's a real bug from iOS nothing else, and no solutions found on stack overflow worked for me (at this date). – Tancrede Chazallet Dec 10 '14 at 10:27

6 Answers6

58

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.

Or Sharir
  • 1,607
  • 12
  • 21
  • 2
    Dude, this comment is golden. – Goles Jan 20 '14 at 19:23
  • 4
    btw, in my case the 'completion block' wasn't really the issue... I was performing animations in view did appear, (that maybe is getting called before the animations finish) ;) – Goles Jan 20 '14 at 19:25
  • Did you get any complete solution for crash in UIPageViewController. – Brjv Sep 23 '14 at 15:42
  • 2
    Amazing time saver.. I was animating some collection view cells and getting this error. Wrapped animate in dispatch and it's gone away. – JeremyDay Dec 03 '14 at 07:33
  • Using the completion handler even for not UI related things broke for me. – orkoden Jul 07 '16 at 15:23
  • check my answer: http://stackoverflow.com/a/40686109/1060785, maybe you have problem in `UIPageViewControllerDelegate` – Vitalii Gozhenko Nov 18 '16 at 21:22
  • I don't know why it happen but I know where it happen. You're totally correct. It happen inside complete block, then I using queue.async in this block, It doesn't happen anymore. – R.Kaka Jan 30 '18 at 07:29
7

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
    }
}];
Korey Hinton
  • 2,532
  • 2
  • 25
  • 24
  • can you please help me with this error? I have tried everybody's solution.. but it's not working Assertion failure in -[_UIQueuingScrollView _replaceViews:updatingContents:adjustContentInsets:animated:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3512.60.7/_UIQueuingScrollView.m:377 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: [views count] == 3' I have used LTPageManger Github project – Krutika Sonawala Aug 11 '16 at 03:29
  • ok I end up with pageView.userInteractionEnabled doing yes and no in viewWillAppear, viewDidAppear & viewWillDisappear. Thanks for your hint. – Krutika Sonawala Aug 11 '16 at 04:00
3

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];
        })
    }
}
Jim Yu
  • 1,236
  • 11
  • 10
  • Should this be a solution to fix the crash? Can you explain? – Ortwin Gentz Jan 27 '17 at 19:46
  • 2
    It fixes the crash. But I don't know why have to dispatch to main queue again, even though it's already in main thread. – Jim Yu Jan 27 '17 at 23:16
  • 1
    I had similar code that triggered some animation in the `pageViewController: didFinishAnimation` delegate method and it crashed randomly when switching pages. Putting the animation call into a `DispatchQueue.main.async` call fixe the crash. – codingFriend1 Apr 16 '18 at 14:17
2

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.

videolist
  • 219
  • 3
  • 4
  • For me this error occurs when using an `input.becomeFirstResponder()` within `viewDidAppear`. The animation was caused by the showing up of the keyboard. – mixable Aug 10 '16 at 18:55
  • @mixable - probably a bit late, but if you wrap `input.becomeFirstResponder` in a dispatch block on the main thread, it might fix the issue for you - it did for me. `[self.pageVC setViewControllers:@[self.currentVC] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:^(BOOL finished) { dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf.currentVC.textField becomeFirstResponder]; }); }];` – Martin Herman Nov 06 '16 at 20:10
1

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

Vitalii Gozhenko
  • 9,220
  • 2
  • 48
  • 66
0

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.

Chris Loer
  • 190
  • 1
  • 12