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:.horizontal,options:nil)
它看起来更好,它不会被调用两次