IOS - UIPageViewControllerDataSource method called twice

I found a strange problem with two methods of UIPageViewControllerDataSource : when I first enter the pageview controller and drag the contents of the controller, regardless of the direction of the drag, both data source methods get called. I believe that when I am on the first page and drag to the right, this means that the page will no longer be in front of the first page, none of the methods should be called. And if I drag left, only the calling method should receive the call.

I completed this post to configure view controllers (except that I do not have a separate pageview controller on the storyboard. I used the traditional [UIPAgeViewController alloc] init] method to create the controller instance). Below is my code:

For a view controller that actually displays the contents of the page view controller (only the corresponding part of viewDidLoad ):

  - (void)viewDidLoad { // initialize page view controller _pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil]; self.pageViewController.delegate = self; self.pageViewController.dataSource = self; // set up the initial scene of the page view controller UIViewController *viewController = [self viewControllerAtIndex:0]; [self.pageViewController setViewControllers:@[viewController] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; // adjust the size of the page view controller, -44 to show the buttons at the bottom self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 44); // display the content of the page view controller [self addChildViewController:self.pageViewController]; [self.view addSubview:self.pageViewController.view]; [self.pageViewController didMoveToParentViewController:self]; } - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { NSUInteger index = ((PWCPageContentViewController *)viewController).index; if (index == 0 || index == NSNotFound) { return nil; } --index; return [self viewControllerAtIndex:index]; } - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { NSUInteger index = ((PWCPageContentViewController *)viewController).index; if (index == self.numberOfPages - 1 || index == NSNotFound) { return nil; } ++index; return [self viewControllerAtIndex:index]; } - (PWCPageContentViewController *)viewControllerAtIndex:(NSUInteger)index { PWCPageContentViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageContentViewController"]; viewController.index = index; NSString *text = [self.notes getNoteAtIndex:index]; [viewController.textView setText:text]; return viewController; } 

For PWCPageContentViewController.h:

 #import <UIKit/UIKit.h> @class PWCNotes; @interface PWCPageContentViewController : UIViewController <UITextViewDelegate> @property NSUInteger index; @property (weak, nonatomic) IBOutlet UITextView *textView; - (void)dismissKeyboard; @end 

For PWCPageContentViewController.m:

 #import "PWCPageContentViewController.h" @interface PWCPageContentViewController () @end @implementation PWCPageContentViewController - (void)viewDidLoad { [super viewDidLoad]; self.textView.delegate = self; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)dismissKeyboard { if ([self.textView isFirstResponder]) { // dismiss the keyboard when hitting save [self.textView resignFirstResponder]; } } @end 

So, is this a known problem or am I missing something?

+7
ios objective-c uipageviewcontroller
source share
4 answers

UIPageViewController uses the following method to get the reverse and front ViewController.

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

Although this is strange, but yes, this is a known issue. Every time he calls the Before and After method to get the VC. If the next VC does not exist, it returns nil , and if the previous VC does not have a datasourceDelegate return no value, otherwise it returns the VC index.

In UIPageViewControllerDelegate there is a function named:

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

Look at this, it can help get the current or next / previous view manager from the pendingViewControllers array.

Hope this helps .. :)

+2
source share

The solution to this problem in Swift :

I encountered an error when using more than 3 UIPageViewController (for example, try with 4 UIPageViewController using the @Rashad snippet). The problem came from the missing and not implemented optional UIPageViewControllerDelegate method, which led to an unsuccessful and unsustainable UIPageControl.

Please find a specific method that fixes the error below:

 /* Optional UIPageViewControllerDelegate method Sent when a gesture-initiated transition ends. The 'finished' parameter indicates whether the animation finished, while the 'completed' parameter indicates whether the transition completed or bailed out (if the user let go early). */ func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [AnyObject], transitionCompleted completed: Bool) { // Turn is either finished or aborted if (completed && finished) { let currentDisplayedViewController = self.pageViewController!.viewControllers[0] as! ContentViewController self.pageControl.currentPage = currentDisplayedViewController.index } } 

If you want a complete working project, please find the Github link below:

( Github project link )

+5
source share

As @Rashad suggested, pageViewController:willTransitionToViewControllers: not corrupted. It is called exactly once when you go to the previous / next view controller (in case the previous / next view controller is not nil ). This also applies to pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted: which is called exactly once when the animation ends.

So, if you want to do some kind of indexed things and want to get the right index for upcoming view controllers or want to get the right view controller, consider using these two methods as a workaround.

+1
source share

change the transition style from scroll to page Curl

pageViewController = UIPageViewController (transitionStyle: .pageCurl, navigationOrientation :. Horizontal, options: nil)

he looks better and he will not be called twice

0
source share

All Articles