Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PageViewController delegate functions called twice

I am working with UIPageViewController , to make a product tour for my application.

I followed this link http://www.appcoda.com/uipageviewcontroller-tutorial-intro/

I am doing is simple task of changing backgound color of my "root VC" on swipe, based on the index value I get, but as the delegate functions are called twice, my index value is not correct and because of that, I am not able to get it right, below is my code

#import "APPViewController.h"
#import "APPChildViewController.h"

@interface APPViewController ()

@end

@implementation APPViewController

- (void)viewDidLoad {

    [super viewDidLoad];

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

    self.pageController.dataSource = self;
    [[self.pageController view] setFrame:CGRectMake(0, 0, 320, 500)];

    APPChildViewController *initialViewController = [self viewControllerAtIndex:0];

    NSArray *viewControllers = [NSArray arrayWithObject:initialViewController];

    [self.pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];

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

}

- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.

}

- (APPChildViewController *)viewControllerAtIndex:(NSUInteger)index {

    APPChildViewController *childViewController = [[APPChildViewController alloc] initWithNibName:@"APPChildViewController" bundle:nil];
    childViewController.index = index;
    childViewController.view.backgroundColor = [UIColor clearColor];

    if(index == 0)
    {
          self.view.backgroundColor = [UIColor redColor];
     }

    if(index == 1)
    {
          self.view.backgroundColor = [UIColor blueColor];
     }

    if(index == 2)
    {
          self.view.backgroundColor = [UIColor greenColor];
     }


    return childViewController;

}

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

    NSUInteger index = [(APPChildViewController *)viewController index];

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

    // Decrease the index by 1 to return
    index--;

   return [self viewControllerAtIndex:index];

}

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

    NSUInteger index = [(APPChildViewController *)viewController index];

    index++;

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

   return [self viewControllerAtIndex:index];

}

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
    // The number of items reflected in the page indicator.
    return 3;
}

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

Please help me out, I am not getting where I am going wrong

Regards Ranjit

like image 608
Ranjit Avatar asked Jul 12 '13 05:07

Ranjit


3 Answers

After looking for a lot.

I receive that:

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController;
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController;

2 functions use to get pageViewController behind or in front of current pageViewController.

I thinks it's difficult to get current pageViewController

My suggestion:

In UIPageViewControllerDelegate, it have a function :

 - (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers;

This function to give you a pendingViewControllers array and this's current pageViewController array. So you can implement like that :

- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers
{


if([pendingViewControllers count]>0)
  {
     NSUInteger index =[(APPChildViewController*)[pendingViewControllers objectAtIndex:0] index];

    if(index == 0)
    {
        self.view.backgroundColor = [UIColor redColor];
    }

    if(index == 1)
    {
        self.view.backgroundColor = [UIColor blueColor];
    }

    if(index == 2)
    {
        self.view.backgroundColor = [UIColor greenColor];
    }


  }
}

In viewDidLoad, you add :

    self.pageController.delegate = self;

    self.view.backgroundColor = [UIColor redColor]; //set first background.

In 'APPViewController.h' you sure add:

@interface APPViewController : UIViewController<UIPageViewControllerDataSource,UIPageViewControllerDelegate>

Remember : remove this code (in 'viewControllerAtIndex' function)

if(index == 1)
{
    self.view.backgroundColor = [UIColor redColor];
}

if(index == 2)
{
    self.view.backgroundColor = [UIColor blueColor];
}

if(index == 3)
{
    self.view.backgroundColor = [UIColor greenColor];
}

Let's me know if you have any questions.

like image 197
Nguyen Thi Thuy Trang Avatar answered Nov 12 '22 21:11

Nguyen Thi Thuy Trang


I faced the same issue and finally figured out the cause . The delegate methods are called twice when the the Transition style for the page view controller is set to " Page Curl".

When the transition style is set to "Page Curl", the action is like turning a page in a book. You turn one page and the page number gets incremented by 2. Applying the same concept for the page view controller, 2 view controllers are transitioned for Page Curl style: one is the view controller you see and the other view controller is on the other side of the curled view.

Change the transition style to "Scroll" and you can get rid of the problem

This can be done from storyboard in the attribute inspector as follows:

check image

You can also change the same by code by setting the UIPageViewController.transitionStyle property to UIPageViewControllerTransitionStyleScroll.

Hope it helps

like image 30
Gurunath Sripad Avatar answered Nov 12 '22 23:11

Gurunath Sripad


Replace these two methods and compile,

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

    NSUInteger index = [(APPChildViewController *)viewController index];
    if (index == 0)
    {
        self. view.backgroundColor = [UIColor redColor];
        return nil;
    }

    if(index == 1)
    {
        self.view.backgroundColor = [UIColor blueColor];
    }

    if(index == 2)
    {
        self.view.backgroundColor = [UIColor greenColor];
    }
    if(index == 3)
    {
        self.view.backgroundColor = [UIColor brownColor];
    }
    /*if(index == 4)
    {
        self.view.backgroundColor = [UIColor whiteColor];
    }*/

    // Decrease the index by 1 to return
    index--;

    return [self viewControllerAtIndex:index];

}

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

    NSUInteger index = [(APPChildViewController *)viewController index];
    /*if(index == 0)
    {
        self.view.backgroundColor = [UIColor redColor];
    }*/
    if(index == 1)
    {
        self.view.backgroundColor = [UIColor blueColor];
    }

    if(index == 2)
    {
        self.view.backgroundColor = [UIColor greenColor];
    }
    if(index == 3)
    {
        self.view.backgroundColor = [UIColor brownColor];
    }
    if(index == 4)
    {
        self.view.backgroundColor = [UIColor whiteColor];
        return nil;
    }

    /*if (index == 5) {
        return nil;
    }*/
    index++;

    return [self viewControllerAtIndex:index];

}

and add this in the end of - (void)viewDidLoad {

self.view.backgroundColor = [UIColor redColor];

like image 1
Baby Groot Avatar answered Nov 12 '22 22:11

Baby Groot