iOS – UIPageViewControllerDataSource方法调用两次

我发现了两个UIPageViewControllerDataSource方法的一个奇怪的问题:第一次进入页面视图控制器场景并拖动控制器的内容时​​,无论拖动方向是什么,都会调用这两个数据源方法。 我想,当我在第一页,并拖动到右侧,这意味着没有更多的页面之前的第一页,这两个方法都不应该被调用。 如果我拖动到左边,只有after方法应该被调用。

我按照这个post设置了视图控制器(除了我在故事板上没有单独的页面视图控制器,我用传统的[UIPAgeViewController alloc] init]方法来实例化控制器)。 以下是我的代码:

对于实际显示页面视图控制器内容的视图控制器(只显示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; } 

对于PWCPageContentViewController.h:

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

对于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 

那么这是一个已知的问题,还是我错过了什么?

UIPageViewController使用下面的方法获取前后的ViewController。

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

尽pipe它很奇怪,但它是一个已知的问题。 每次调用Before和After方法来获得VC。 如果没有下一个VC,则返回nil ,如果没有以前的VC,则datasourceDelegate返回nil,否则返回VC的索引。

UIPageViewControllerDelegate ,有一个名为:

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

看看这可能有助于从pendingViewControllers数组获取当前或下一个/上一个pendingViewControllers

希望这可以帮助.. :)

Swift中解决这个问题的方法是:

当我使用3个以上的UIPageViewController时遇到了这个错误(例如使用4个UIPageViewController ,使用@ Rashad的代码片段)。 问题来自一个缺less和未实现的可选UIPageViewControllerDelegate的方法,这使得UIPageControl疯狂和不稳定。

请find修复以下错误的特定方法:

 /* 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 } } 

如果你想得到完整的工作项目,请find下面的Github链接:

( 该项目的Github链接 )

所以@Rashadbuild议, pageViewController:willTransitionToViewControllers:不会混淆。 当您转换到上一个/下一个视图控制器时(在上一个/下一个视图控制器不是nil情况下),它只会被调用一次。 这也适用于pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:当animation结束时, pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:被调用一次。

所以,如果你想做任何基于索引的事情,并且你想为即将到来的视图控制器获得正确的索引,或者你想获得正确的视图控制器,那么现在考虑使用这两种方法作为解决方法。

将过渡样式从滚动更改为pageCurl

pageViewController = UIPageViewController(transitionStyle:.pageCurl,navigationOrientation:.horizo​​ntal,options:nil)

它看起来更好,它不会被调用两次