Gili Ariel
Gili Ariel

Reputation: 602

UIPageViewControllerDataSource calls viewControllerAfterViewController twice the first time running

I know this might be a duplicate but I tried other solutions found online and none of them seemed to solve my problem.

I have a pageViewController that displays 4 UIViewControllers. At first scroll the pageController swipes to the third View controller but shows the second ViewController.

Here is my code:

_contentPageRestorationIDs = [[NSArray alloc]initWithObjects:@"PRPeripheralsOriantaionVC",@"PRSessionAnalysisDataVC", @"PRNavigationVC",@"PRVideoVC", nil];


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

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
        NSString *vcRestorationID = viewController.restorationIdentifier;
    NSUInteger index = [self.contentPageRestorationIDs indexOfObject:vcRestorationID];
    NSLog(@"viewControllerBeforeViewController %@",vcRestorationID);

    if (index == 0)
    {
        return nil;
    }

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

}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    NSString *vcRestorationID = viewController.restorationIdentifier;
NSLog(@"viewControllerAfterViewController %@",vcRestorationID);

    NSUInteger index = [self.contentPageRestorationIDs indexOfObject:vcRestorationID];
    index ++;
    if (index == self.contentPageRestorationIDs.count )
    {
        return nil;
    }

    return [self viewControllerAtIndex:index ];

}
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers
{
   NSLog(@"willTransitionToViewControllers %@ %lu",pendingViewControllers,(unsigned long)index);

}

-(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
NSLog(@"didFinishAnimating %@",previousViewControllers);
}

Upvotes: 0

Views: 1576

Answers (2)

Guy Kahlon
Guy Kahlon

Reputation: 4520

You have a bug, Update your datasource method:

h File

@interface ViewController : UIPageViewController

@end

m File

#import "ViewController.h"

@interface ViewController ()<UIPageViewControllerDataSource>
@property (strong, nonatomic) NSArray *pageColors;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.pageColors = @[@"green", @"yellow", @"black", @"red"];
    self.dataSource = self;


    UIViewController *startingViewController = [self viewControllerAtIndex:0];
    NSArray *viewControllers = @[startingViewController];
    [self setViewControllers:viewControllers
                   direction:UIPageViewControllerNavigationDirectionForward
                    animated:NO
                  completion:nil];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Private method
- (UIViewController *)viewControllerAtIndex:(NSUInteger)index
{
    if (([self.pageColors count] == 0) || (index >= [self.pageColors count])) {
        return nil;
    }

    NSString* pageColor = self.pageColors[index];

    // Create a new view controller and pass suitable data.
    UIViewController *pageContentViewController = [self.storyboard instantiateViewControllerWithIdentifier:pageColor];

    return pageContentViewController;
}

#pragma mark - Page View Controller Data Source
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
      viewControllerBeforeViewController:(UIViewController *)viewController
{
    NSString * identifier = viewController.restorationIdentifier;
    NSUInteger index = [self.pageColors indexOfObject:identifier];

    if ((index == 0) || (index == NSNotFound)) {
        return nil;
    }

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

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
       viewControllerAfterViewController:(UIViewController *)viewController
{
    NSString * identifier = viewController.restorationIdentifier;
    NSUInteger index = [self.pageColors indexOfObject:identifier];

    if (index == NSNotFound) {
        return nil;
    }

    index++;
    if (index == [self.pageColors count]) {
        return nil;
    }
    return [self viewControllerAtIndex:index];
}

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

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

enter image description here

Don't forget to change for each view controller the Storyboard ID with his color ([@"green", @"yellow", @"black", @"red"]). For example, for the read view controller:

enter image description here

You can find here very useful tutorial.

Upvotes: 1

Daniel Meltzer
Daniel Meltzer

Reputation: 107

The correct way to do that is to define pageIndex property for each view controller, and then set it in the page view delegate methods, using the view controller at index method, your final wanted code should be the page view delegate methods, passing an index to the view controller at index path and returning there retrieved VC and that's it.

Upvotes: 0

Related Questions