UIPageViewController transition 'Unbalanced calls to begin/end appearance transitions for '

Basem Saadawy picture Basem Saadawy · Nov 6, 2012 · Viewed 11.9k times · Source

When I navigate through UIPageViewController faster than its transition animation I am getting 'Unbalanced calls to begin/end appearance transitions for <MyDataViewController>' and one of the two views in landscape isn't shown until I try to turn the page.

Anybody has an idea to solve this bug?

Answer

Bill Cheswick picture Bill Cheswick · Feb 11, 2013

The above answers were right, but I think more elaborate than needed, and cookbook is helpful. So here is what seems to be working for me:

In the view controller that sets up and calls the pageViewController, declare:

@property (assign)              BOOL pageIsAnimating;

and in viewDidLoad:

    pageIsAnimating = NO;

add this:

- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers {
    pageIsAnimating = YES;
}

and add a couple of lines to:

- (void)pageViewController:(UIPageViewController *)pageViewController
    didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers
   transitionCompleted:(BOOL)completed {
    if (completed || finished)   // Turn is either finished or aborted
        pageIsAnimating = NO;
    ...
}

The gestures are suppressed by declining to provide view controller information:

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
   viewControllerAfterViewController:(UIViewController *)viewController {
    if (pageIsAnimating)
        return nil;
    ...
    return after;
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
  viewControllerBeforeViewController:(UIViewController *)viewController {
    if (pageIsAnimating)
        return nil;
    ...
    return before;
}

Oh, and orientation changes reset the flag:

- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController
               spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation {
    pageIsAnimating = NO;
    ...
}