Assertion failure in UIQueuingScrollView didScrollWithAnimation:force:

Fogmeister picture Fogmeister · Oct 16, 2012 · Viewed 7.3k times · Source

I've got a UIPageViewController set up paging my ImageViewController.

The ImageViewController contains a UIScrollView with a UIImageView inside. Nothing else.

I'm testing at the moment with 3 "items" in my datasource for the UIPageViewController (i.e. three pages).

It all works fine and I can scroll and zoom and then page for about 30 seconds and then suddenly I get this warning...

*** Assertion failure in -[_UIQueuingScrollView _didScrollWithAnimation:force:], /SourceCache/UIKit/UIKit-2372/_UIQueuingScrollView.m:778

I've got no idea where to start debugging it though as it doesn't point to any of my code and there isn't any of my code in the stack or anything.

Can someone give me a pointer as to where to start debugging this.

EDIT

I've done a bit more testing. It seems to happen if the scrollView is decelerating (i.e. after a flick) and then I try to transition the PageViewController to another ViewController as the scrollview is still moving.

The app crashes about 20% of the way through the transition to the next page.

EDIT 2

The error seems to stop on the line _cache_getImp (not sure if that's a capital i or lowercase L).

EDIT 3

This gets better. I just downloaded Apple's PhotoScroller sample app to see if they got round the problem a different way. Well, no, they didn't. The sample app crashes in exactly the same way mine does! You have to zoom and scroll and transition pages at the same time to make it more likely to crash but it happens on it's own too it just might take longer to happen.

Answer

Kyle Clegg picture Kyle Clegg · Dec 14, 2013

Came up with a solution! In my case I have a UIPageViewController with UIPageViewControllerTransitionStyleScroll as well as next buttons that allow the user to advance through my viewpager by tapping. I am getting this crash when the user presses a next button and drags around slightly before releasing their finger (still within the frame of the button). It appears that the dragging within the button is interfering with UIPageViewController's pan gesture recognizer in this case, and that's what causes the crash.

While it's pretty unlikely that the user will get in this state, I've come up with a relatively simple solution the prevents my app from crashing if it does happen. I have a boolean that represents if the user is in a valid state to move to the next screen and set it to YES on touch down, then to NO if the user drags anywhere inside my button. Then, on touchUp (nextPressed) I check the boolean before moving my UIPageViewController programatically.

- (IBAction)touchDown:(id)sender
{
  self.shouldAdvanceToNextScreen = YES;
}

- (IBAction)touchDragInside:(id)sender
{
  self.shouldAdvanceToNextScreen = NO;
}

- (IBAction)nextPressed:(id)sender
{
  if (self.shouldAdvanceToNextScreen) {
    UIViewController *initialViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"TutorialScreen2"];
    NSArray *viewControllers = [NSArray arrayWithObject:initialViewController];
    [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
  }
}

The downside is that nothing will happen even though the user still released their finger within the button frame. However, I prefer this over a crash and see this as a pretty rare edge case regardless. I'd expect the user would just tap again - this time without a tap & drag - and move forward successfully.

I'd welcome any ideas on taking this a step further and preventing the clash between the touch drag and the UIPageViewController altogether.