6

I want to keep track of the index using the UIPageViewController. Whenever I swipe I need to index++ or index--. This delegate method gets called whenever you swipe back or further:

- (void)pageViewController:(UIPageViewController *)pvc didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
    // If the page did not turn
    if (!completed)
    {
        // You do nothing because whatever page you thought
        // the book was on before the gesture started is still the correct page
        return;
    }

    // I want to check here whenever the page was swiped back or further
}

How do I check in this method if the user swiped back or further? I know there are the 2 DataSource methods "viewControllerAfterViewController" and "viewControllerBeforeViewController" but I cannot check if the page transition has completed (and I can do this in the above method) any idea how I could know if the user swiped back or further in the above method?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
nonuma
  • 399
  • 1
  • 3
  • 14

4 Answers4

6

use protocol:

MyClass : UIViewController <UIPageViewControllerDataSource,UIPageViewControllerDelegate

declare a atributes:

@property(nonatomic) NSInteger currentIndex;
@property(nonatomic) NSInteger nextIndex;

and in the methods:

-(void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers{
    NewsTableViewController *controller  = [pendingViewControllers firstObject];
    self.nextIndex = [self.arrViews indexOfObject:controller];
}

-(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{
    if (completed) {
        self.currentIndex = self.nextIndex;
    }
    self.nextIndex = 0;
}

there you will have the current page. Thanks to Corey Floyd in enter link description here

Community
  • 1
  • 1
  • `nextIndex` should be equal `currentIndex + 1`. In `didFinishAnimating`, check new `currentIndex == nextIndex`, it is swipe left, else is right – huynguyen Apr 22 '16 at 08:19
4

According to the documentation there does not appear to be a way to tell whether the user has swiped the page forward or backward. The boolean 'finished' will tell you whether or not the user has completed the page turn.

A workaround:

Create an int variable and using the viewControllerAfterViewController and viewControllerBeforeViewController methods either increase or decrease the value of the variable. Use that to test whether or not they moved forward or backward.

Edit: You could use presentationIndexForPageViewController from the documentation

Edit 2: Check this link here There is a method named setViewControllers:direction:animated:completion: the direction will be either UIPageViewControllerNavigationDirectionForward or UIPageViewControllerNavigationDirectionReverse

Edit 3: Code - This is assuming you know which view controller will be called by either going forward or backward:

Create a variable on your appDelegate and a setter method:

int indexVar;

- (void)setIndex:(int)indexVar;

Then on your view controllers (forward or backward) either increase the value or decrease the value (viewDidLoad):

(AppDelegate *)[[UIApplication sharedApplication] delegate] setIndex:<whatever>];

Something along those lines. This won't be an exact way to accomplish your goal, but hopefully it will get you headed in the right direction.

Jordan
  • 2,992
  • 2
  • 20
  • 29
  • The problem with that is that I cannot keep track of the index in those 2 functions... Because I canno't check if the transition was completed, if it wasn't completed the index doesn't need to increase or decrease (ea if you grab the page but don't turn it to the next page) – nonuma Apr 24 '13 at 20:55
  • 1
    I have edited my answer to reflect your comments. The presentationIndex won't change up or down unless the user has gone forward or backward. – Jordan Apr 24 '13 at 21:01
  • And how do I use that method? Can you give me a little example how I index++ and index-- ? – nonuma Apr 24 '13 at 21:05
  • I use the setViewControllers method (Sets the view controllers to be displayed.) to initialiaze the UIPageViewController with the first viewController... – nonuma Apr 24 '13 at 21:09
  • 1
    The answer is on the page referenced under Edit 2 of my answer. In that instance method that is an argument called completion which is a block to be called when the page-turn animation completes or does not complete. – Jordan Apr 24 '13 at 21:16
  • 1
    I see. Well then the way to go is the variable. Let me update my answer with the code – Jordan Apr 24 '13 at 21:28
  • Wouldn't this index var be more useful in the UIPageViewController's actual view controller? See my [answer here](http://stackoverflow.com/a/25714713/947342) for an example. Then you could handle all of this within the view controller itself—where I believe it actually belongs. :] – pxpgraphics Sep 07 '14 at 21:01
  • I'm using viewControllerAfterViewController and viewControllerBefore for callback to another view controller(parent of pageviewController) to know user had swipe reverse or forward but even for single swipe both are calling like viewControllerAfterViewController and this viewControllerBefore and then again viewControllerAfterViewController don't know why? any idea? – Iraniya Naynesh Mar 22 '18 at 14:28
0

I did it by creating protocols in each of my ViewController classes, with the protocol method called in the viewWillAppear method. Then in the PageViewController whenever I instantiate one of the view controllers I set its delegate to be the PageViewController. This is the 3rd ViewController in my project(Note that I've done this in each of my view controllers)

@class ViewController3;
@protocol ViewControllerPageNumber <NSObject>

-(void)viewWillAppearMyPageNumber:(int)myPageNumber;

@end
@interface ViewController3 : UIViewController
@property (nonatomic, weak) id <ViewControllerPageNumber> delegate;
@end

and in the .m file in the viewWillAppear method

-(void)viewWillAppear:(BOOL)animated{
    [self.delegate viewWillAppearMyPageNumber:3];//The 3 will be different for each ViewController 
}

Next, in the PageViewController.m, whenever I instantiate a view controller I set its delegate to be self( or PageViewController). viewCons is just an array of strings with my viewControllers names.

- (UIViewController *)viewControllerAtIndex:(NSUInteger)index {
    id vc = [[NSClassFromString([viewCons objectAtIndex:index]) alloc] init];
    if([vc isMemberOfClass:[NSClassFromString(@"ViewController3") class]]){
        ViewController3 *vc3=(ViewController3 *) vc;
        vc3.delegate=self;
    }else if([vc isMemberOfClass:[NSClassFromString(@"ViewController2") class]]){
        ViewController2 *vc2=(ViewController2 *) vc;
        vc2.delegate=self;
    }else if([vc isMemberOfClass:[NSClassFromString(@"ViewController") class]]){
        ViewController *vc1=(ViewController *) vc;
        vc1.delegate=self;
    }
    return vc;
}

Finally, I'm implementing my custom delegate method, which in my case is refreshing labels' text I have set on top of the PageViewController.

-(void)viewWillAppearMyPageNumber:(int)myPageNumber{
    [self refreshLabelsOnCurrentPageWithIndex:myPageNumber];
}
Objectif
  • 364
  • 1
  • 4
  • 12
0

I think the easiest solution is to to create an own ViewController class with a property that keeps track of the currently shown index. In most of the cases I need a custom ViewController for my PageViewController anyways. In my example this is the following class.

@interface PageZoomViewController : UIViewController

@property (nonatomic) int pageIndex;

@end

Then in the viewControllerAfter/Before methods you can pass the index to the new page.

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

    int nextPageIndex = ((PageZoomViewController *)viewController).pageIndex-1;

    PageZoomViewController *controller = [[PageZoomViewController alloc] initWithPageViewControlParent:self andFrame:[self frameForPagingScrollView] andPageIndex:nextPageIndex];

    return controller;
}

When the animation for the next page finished you can easily set the current index like this.

-(void)pageViewController:(UIPageViewController *)thePageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {

    if(completed) {
        index = ((PageZoomViewController *)thePageViewController.viewControllers[0]).pageIndex;
    }
}

Hope this helps!

Philipp Otto
  • 4,061
  • 2
  • 32
  • 49