Search code examples
iosobjective-cuipageviewcontroller

UIPageViewController does not work properly


I'm developing an iOS app and I imeplementes a Demo Tour for the app using UIPageViewController, on each view controller I show an image and a video, but the methods

 pageViewController:ViewControllerBeforeViewController
 pageViewController:ViewControllerAfterViewController

are not working properly, sometimes it jumps to another page that is not the next one or the previous one. It only occurs when I use swipe gestures to pass the pages if I tap on the page indicator (UIPageControl) it works correctly.

My code:

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
  NSUInteger index = ((DemoTourViewController*) viewController).pageIndex;

  if (index == NSNotFound)
    return nil;

  // If the current page is the first one then go back to the last one
  if (index == 0)
    index = [self.pageTitles count];

  index--;
  return [self viewControllerAtIndex:index];
 }

 - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
 {
  NSUInteger index = ((DemoTourViewController*) viewController).pageIndex;

  if (index == NSNotFound)
    return nil;

  index++;

  // If the current page is the last one then just start again (go in circle)
  if (index == [self.pageTitles count])
    index = 0;

  return [self viewControllerAtIndex:index];
}

I printed on my log the index values and it represents just that I was explained, i.e. index is 2 and after swipe is 4 (it should be 3) but in the device shows the third page with the third image but can't play the third video and only reproduce the sound of the fourth video. That isn't occurs when I tap on the page control indicator.

Edit

There are the rest of methods that I have in my PageViewcontroller

- (DemoTourViewController *)viewControllerAtIndex:(NSUInteger)index
{
  if (([self.pageTitles count] == 0) || (index >= [self.pageTitles count])) {
    return nil;
  }

  // Create a new view controller and pass suitable data.
  DemoTourViewController *pageContentVC = [self.storyboard instantiateViewControllerWithIdentifier:@"DemoTourViewController"];
  pageContentVC.imageFile = self.pageImages[index];
  pageContentVC.titleText = self.pageTitles[index];
  pageContentVC.pageIndex = index;
  pageContentVC.videoPath = [[NSBundle mainBundle]pathForResource:self.pageVideos[index] ofType:@"mp4"];
  pageContentVC.backgroundImgView.userInteractionEnabled = YES;

  return pageContentVC;
}

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
  return [self.pageTitles count]; 
}

- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
  return 0;
}

Solution

  • Well, I thought about it overnight and I think your problem comes from starting the movie playing in the viewDidLoad method. It seems that when you use swipe gestures to switch pages, say from page 2 to page 3, the pageViewController not only loads and displays page 3, it also pre-emptively loads page 4. Presumably this is a performance optimisation, so if you swipe quickly again it has already loaded the next page. However, in your case this triggers the movie at index 4 to play (which you can hear, but not see, since that page has not yet been displayed). And because only one movie can be playing at a time, the movie on page 3 stops.

    So, to fix it, I would change your code so that the movie only begins playing once the page is actually on screen. I think it will work OK if you move [self.player play] to the viewDidAppear: method. Happy to answer any questions via the chat session.