Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8787433
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 13, 20262026-06-13T21:53:30+00:00 2026-06-13T21:53:30+00:00

I have a really interesting issue with UIPageViewController. My project is set up very

  • 0

I have a really interesting issue with UIPageViewController.

My project is set up very similarly to the example Page Based Application template.
Every now and then (but reproducible to a certain extent) a certain pan gesture will call out to -(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController.

I return the viewcontroller for the next page, but a page flip animation is never ran and my delegate method is never called.

Here is the code for viewControllerAfterViewController

-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    PageDisplayViewController *vc = (PageDisplayViewController *)viewController;
    NSUInteger index = [self.pageFetchController.fetchedObjects indexOfObject:vc.page];
    if(index == (self.pageFetchController.fetchedObjects.count - 1)) return nil;
    return [self getViewControllerForIndex:(++index)];
}

Here is the getViewControllerForIndex:

-(PageDisplayViewController *)getViewControllerForIndex:(NSUInteger)index
{
    PageDisplayViewController *newVC = [self.storyboard instantiateViewControllerWithIdentifier:@"PageDisplayController"];
    newVC.page = [self.pageFetchController.fetchedObjects objectAtIndex:(index)];
    newVC.view.frame = CGRectMake(0, 0, 1024, 604);
    NSLog(@"%i", index);
    if(index == 0)
    {
        //We're moving to the first, animate the back button to be hidden.
        [UIView animateWithDuration:0.5 animations:^
        {
            self.backButton.alpha = 0.f;
        } completion:^(BOOL finished){
            self.backButton.hidden = YES;
        }];
    }
    else if(index == (self.pageFetchController.fetchedObjects.count - 1))
    {
        [UIView animateWithDuration:0.5 animations:^{
            self.nextButton.alpha = 0.f;
        } completion:^(BOOL finished){
            self.nextButton.hidden = YES;
        }];
    }
    else
    {
        BOOL eitherIsHidden = self.nextButton.hidden || self.backButton.hidden;
        if(eitherIsHidden)
        {
            [UIView animateWithDuration:0.5 animations:^{
                if(self.nextButton.hidden)
                {
                    self.nextButton.hidden = NO;
                    self.nextButton.alpha = 1.f;
                }
                if(self.backButton.hidden)
                {
                    self.backButton.hidden = NO;
                    self.backButton.alpha = 1.f;
                }
            }];
        }
    }
    return newVC;
}

Basically, I create the view controller, set it’s data object, then fade a next/back button out depending on the index.

Delegate method

-(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
    PageDisplayViewController *vc = [previousViewControllers lastObject];
    NSUInteger index = [self.pageFetchController.fetchedObjects indexOfObject:vc.page];

    if (!completed)
    {
        [self.pagePreviewView setCurrentIndex:index];
        NSLog(@"Animation Did not complete, reverting pagepreview");
    }
    else
    {
        PageDisplayViewController *curr = [pageViewController.viewControllers lastObject];
        NSUInteger i = [self.pageFetchController.fetchedObjects indexOfObject:curr.page];
        [self.pagePreviewView setCurrentIndex:i];
        NSLog(@"Animation compeleted, updating pagepreview. Index: %u", i);
    }
}

I only noticed this issue because randomly, my back button would reappear on screen. After tossing some NSLog() statements in there, I notice that my dataSource method gets called for an index of 1, but no animation ever plays or delegate gets called. Whats even scarier, is that if I try to pan the next page, index 1 gets called for AGAIN.

I fear this may be a bug with the UIPageViewController.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-13T21:53:31+00:00Added an answer on June 13, 2026 at 9:53 pm

    Please look at my other answer in the first place, this one has serious flaws but I’m leaving it here as it might still help someone.


    First off, a disclaimer: The following solution is a HACK. It does work in the environment I tested but there is no guarantee that it works in yours nor that it won’t be broken by the next update. So proceed with care.

    TL;DR: grab the UIPanGestureRecognizer of the UIPageViewController and hijack its delegate calls but keep forwarding them to the original target.

    Longer version:

    My findings on the issue: the UIPageViewController shipped in iOS 6 is different in behavior to the one in iOS 5 in that it may call the pageViewController:viewControllerBeforeViewController: on its datasource even if there is no page turning going on in any sense (read: no tap, swipe, or valid direction-matching panning has been recognized). This, of course, breaks our former assumption that the before/after calls are equivalent to an “animation begin” trigger and are consistently followed by a pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted: call to the delegate. (Eventually this is a bold assumption to make but I guess I was not alone with that.)

    I found out that the extra calls to the datasource are likely to happen when the default UIPanGestureRecognizer on the page view controller starts to recognize a pan gesture that in the end doesn’t match the direction of the controller (e.g. vertical panning in a horizontally paging PVC). Interestingly enough, in my environment it was always the “before” method which got hit, never the “after”. Others suggested interfereing with the gesture recognizer’s delegate but that didn’t work for me the way it was described there so I kept experimenting.

    Finally I found a workaround. First we grab the pan gesture recognizer of the page view controller:

    @interface MyClass () <UIGestureRecognizerDelegate>
    {
        UIPanGestureRecognizer* pvcPanGestureRecognizer;
        id<UIGestureRecognizerDelegate> pvcPanGestureRecognizerDelegate;
    }
    ...
    for ( UIGestureRecognizer* recognizer in pageViewController.gestureRecognizers )
    {
        if ( [recognizer isKindOfClass:[UIPanGestureRecognizer class]] )
        {
            pvcPanGestureRecognizer = (UIPanGestureRecognizer*)recognizer;
            pvcPanGestureRecognizerDelegate = pvcPanGestureRecognizer.delegate;
            pvcPanGestureRecognizer.delegate = self;
            break;
        }
    }
    

    Then we implement the UIGestureRecognizerDelegate protocol in our class:

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
    {
        if ( gestureRecognizer == pvcPanGestureRecognizer &&
            [pvcPanGestureRecognizerDelegate respondsToSelector:@selector(gestureRecognizer:shouldReceiveTouch:)] )
        {
            return [pvcPanGestureRecognizerDelegate gestureRecognizer:gestureRecognizer
                                                   shouldReceiveTouch:touch];
        }
        return YES;
    }
    
    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
        shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
    {
        if ( gestureRecognizer == pvcPanGestureRecognizer &&
            [pvcPanGestureRecognizerDelegate respondsToSelector:@selector(gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)] )
        {
            return [pvcPanGestureRecognizerDelegate gestureRecognizer:gestureRecognizer
                   shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer];
        }
        return NO;
    }
    
    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
    {
        if ( gestureRecognizer == pvcPanGestureRecognizer &&
            [pvcPanGestureRecognizerDelegate respondsToSelector:@selector(gestureRecognizerShouldBegin:)] )
        {
            return [pvcPanGestureRecognizerDelegate gestureRecognizerShouldBegin:gestureRecognizer];
        }
        return YES;
    }
    

    Apparently, the methods don’t do anything sensible, they just forward the invocations to the original delegate (making sure that that actually implements them). Still, this forwarding seems to be sufficient for the PVC to behave and not call the datasource when there is no need to.

    This workaround fixed the issue for me on devices running iOS 6. Code which was compiled with the iOS 6 SDK but with a deployment target of iOS 5 had already run flawlessly on 5.x devices, so the fix is not necessary there but according to my tests it doesn’t do any harm either.

    Hope someone finds this useful.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a really interesting case: I have a site where this is already
I have started playing around with Berkeley DB. This one is really interesting, but
I have an interesting issue involving the relationship between sibling layers in a Core
I have a Spring, Hibernate, and Wicket application set up to read internationalized json
I have a really odd issue with an ItemRenderer. I have a main.mxml container
It's an interesting problem, really, for all you Devise masters you there. We have
I have really simple XML (HTML) parsing ANTLR grammar: wiki: ggg+; ggg: tag |
I have really basic question. How can I get form id by input element
I have really no idea why I'm asking this as this a really completely
Im new to iPhone development and I have really taken this to me. I

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.