Question

I've been trying to use the UIPageViewController to display 3 different nibs for a few days on and off now and have almost got it working. I still have one weird bug that I cant figure out.

Basically the app starts, I can scroll between the 3 pages one after another with out any problems, eg:

Page1->Page2->Page3

and then back to the start:

Page3->Page2->Page1.

No Problems. The issue is that if I scroll, for example from Page3->Page2, then BACK to Page3, Page3 Dissappears when it snaps into place. If I scroll to where a forth page would be, then I get Page3. Here is the code relevant to the UIPageViewController, the nibs and the delegate methods for the UIPageViewController:

- (void)viewDidLoad{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];

    self.pageViewController.delegate = self;
    [[self.pageViewController view] setFrame:[[self view] bounds]];

    indexTest = 0;

    Page1 *p1 = [[Page1 alloc]initWithNibName:@"Page1" bundle:nil];
    p1.view.tag = 1;

    Page2 *p2 = [[Page2 alloc]initWithNibName:@"Page2" bundle:nil];
    p2.view.tag = 2;

    Page3 *p3 = [[Page3 alloc]initWithNibName:@"Page3" bundle:nil];
    p3.view.tag = 3;

    NSArray *arr = [[NSArray alloc] initWithObjects:p1,nil];
    viewControllers = [[NSMutableArray alloc] initWithObjects:p1,p2,p3, nil];

    [self.pageViewController setViewControllers:arr direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];

    self.pageViewController.dataSource = self;

    [self addChildViewController:self.pageViewController];
    [[self view] addSubview:[self.pageViewController view]];
    [self.pageViewController didMoveToParentViewController:self];

    self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
}


#pragma mark - page view controller stuff
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {

    if (indexTest > 0) {
        switch (indexTest) {

            case 1:{
                NSLog(@"NO page is BEFORE current page");
                break;
            }
            case 2:{
                NSLog(@"Page BEFORE is Page: %@", [NSString stringWithFormat:@"%@",[viewControllers objectAtIndex:0] ] );
                indexTest--;
                return [viewControllers objectAtIndex:0];
                break;
            }
            default:{
                NSLog(@"PROBLEM  in viewBEFORE, indexTest = %d!!!!", indexTest);
                break;
            }
        }

   }
    return nil;
}



- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {

    if (indexTest < NUM_OF_PAGES) {
        switch (indexTest) {

            case 0:{
                NSLog(@"Page AFTER is Page: %@", [NSString stringWithFormat:@"%@",[viewControllers objectAtIndex:1] ] );
                indexTest++;
                return [viewControllers objectAtIndex:1];
                break;
            }
            case 1:{
                NSLog(@"Page AFTER is Page: %@", [NSString stringWithFormat:@"%@",[viewControllers objectAtIndex:2] ] );
                indexTest++;
                return [viewControllers objectAtIndex:2];
                break;
            }
            case 2:{
                NSLog(@"No pages AFTER this current page %d", indexTest);
                break;
            }
            default:{
                NSLog(@"PROBLEM  in viewAFTER, indexTest = %d!!!!", indexTest);
                break;
            }
        }

    }
    return nil;

}

Finally the page index dots code

#pragma mark - dot controller
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
    // The number of items reflected in the page indicator.
    return NUM_OF_PAGES;
}

- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
    // The selected item reflected in the page indicator.
    return 0;
}

Any and all help is much appreciated, I think I'm just doing something silly that I cant see as I'm so close to it fully working. If anythings not clear or I haven't give enough information please let me know and I'll answer it as best as I can.

Thanks

Was it helpful?

Solution

I think your indexTest logic is wrong, it's showing the wrong indexes for the viewControllers. I wouldn't use those methods to keep track of the index as they can be called even when the views aren't actually going to change.

Instead you could replace the selection of view controllers like this:

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {

    int vcIndex = [self.viewControllers indexOfObject:viewController];
    if (vcIndex > 0) {
        return [self.viewControllers objectAtIndex:vcIndex-1];
    }
    return nil;
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {

    int vcIndex = [self.viewControllers indexOfObject:viewController];
    if (vcIndex < NUM_OF_PAGES-1) {
        return [self.viewControllers objectAtIndex:vcIndex+1];
    }
    return nil;
}

And if you need to keep track of the current index, use the delegate method provided.

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
    if (completed && finished) {
        UIViewController *currentVC = pageViewController.viewControllers[0];
        indexTest = [self.viewControllers indexOfObject:currentVC];
    }
}

Just note that if your using this method, don't call setViewControllers: amimated:YES as this will lose track of the correct position.

Side note: I too have been struggling with UIPageViewController and found it was quicker and easier to write my own version. I think it has too many bugs.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top