以编程方式更改UIPageViewController的页面不会更新UIPageControl

在我的自定义UIPageViewController类中:

 - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { self.model = [[BSTCMWelcomingPageViewModel alloc] init]; self.dataSource = self.model; self.delegate = self; self.pageControl = [UIPageControl appearance]; self.pageControl.pageIndicatorTintColor = [UIColor lightGrayColor]; self.pageControl.currentPageIndicatorTintColor = [UIColor blackColor]; } return self; } 

然后我编程设置当前的ViewController当一个button被击中:

 - (void)scrollToNext { UIViewController *current = self.viewControllers[0]; NSInteger currentIndex = [self.model indexForViewController:current]; UIViewController *nextController = [self.model viewControllerForIndex:++currentIndex]; if (nextController) { NSArray *viewControllers = @[nextController]; // This changes the View Controller, but PageControl doesn't update [self setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil]; //Nothing happens! [self.pageControl setCurrentPage:currentIndex]; //Error: _installAppearanceSwizzlesForSetter: Not a setter! [self.pageControl updateCurrentPageDisplay]; } } 

如果我不能用属于我的UIPageViewControllerUIPageControl来做到这一点,我只会尝试做我自己的。 但如果这是可能的,这将是很好的!

要更新您的UIPageControl指标,您需要实现UIPageViewController(UIPageViewControllerDataSource方法)的一个数据源方法:

 -(NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController 

这个方法负责更新页面控制指示器(当你使用UIPageViewController的时候)。 您只需要返回此方法中的当前页面值。 当您在自定义UIPageViewController上使用/调用setViewControllers时,方法会被默认调用。

所以你需要编写的代码块是:

 - (void)scrollToNext { UIViewController *current = self.viewControllers[0]; NSInteger currentIndex = [self.model indexForViewController:current]; UIViewController *nextController = [self.model viewControllerForIndex:++currentIndex]; if (nextController) { NSArray *viewControllers = @[nextController]; // This changes the View Controller and calls the presentationIndexForPageViewController datasource method [self setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil]; } - (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController { return currentIndex; } 

希望这可以解决你的问题。 🙂

正如接受的答案中所提到的,您需要执行

 - (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController 

但是对我来说,就像这样使用它就足够了:

 - (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController { // The selected item reflected in the page indicator. return [self.controllers indexOfObject:[pageViewController.viewControllers firstObject]]; } 

不需要记住当前的索引。 self.controllers是在给定的UIPageViewController显示的UIViewControllersNSArray 。 我不确定您的BSTCMWelcomingPageViewModel是如何工作的,但它应该很容易调整。

如果两个方法都实现,则页面指示符将可见,过渡样式为UIPageViewControllerTransitionStyleScroll ,导航方向为UIPageViewControllerNavigationOrientationHorizontal 。 这两种方法都是为了响应setViewControllers:...调用而调用的,但是在手势驱动导航的情况下,演示索引会自动更新。

  • (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController NS_AVAILABLE_IOS(6_0); :页面指示符中反映的项目数量。

  • (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController NS_AVAILABLE_IOS(6_0); :所选项目反映在页面指示器中。

上面的答案是由aansul给出的。

注意:不要忘记将pageViewController的Transition样式设置为Scroll而不是Page Curl。 否则,它将无法正常工作。

 // ViewController.h File #import <UIKit/UIKit.h> #import "PageContentViewController.h" @interface ViewScreen : UIViewController<UIPageViewControllerDataSource,UIPageViewControllerDelegate> - (IBAction)Startwalkthrough:(id)sender; @property(strong, nonatomic)UIPageViewController *pageViewController; @property(strong, nonatomic)NSArray * pageTitles; @property(strong,nonatomic)NSArray * pageImages; @end // ViewController.m File #import "ViewScreen.h" @interface ViewScreen () @end @implementation ViewScreen @synthesize pageTitles,pageImages; - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. pageTitles =@[@"dianna",@"images",@"image",@"i1",@"hulk1",@"assasins"]; pageImages =@[@"dianna",@"images",@"image",@"i1",@"hulk1",@"assasins"]; self.pageViewController =[self.storyboard instantiateViewControllerWithIdentifier:@"PageViewController"]; self.pageViewController.dataSource=self; PageContentViewController *startingViewController = [self viewControllerAtIndex:0]; NSArray * viewController =@[startingViewController]; [self.pageViewController setViewControllers:viewController direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; [self addChildViewController:_pageViewController]; [self.view addSubview:_pageViewController.view]; [self.pageViewController didMoveToParentViewController:self]; } -(IBAction)Startwalkthrough:(id)sender { PageContentViewController * startingViewController =[self viewControllerAtIndex:0]; NSArray * viewControllers =@[startingViewController]; [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil]; } - (PageContentViewController *)viewControllerAtIndex:(NSUInteger)index { if (([self.pageTitles count] == 0) || (index >= [self.pageTitles count])) { return nil; } // Create a new view controller and pass suitable data. PageContentViewController *pageContentViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageContentViewController"]; pageContentViewController.imageFile = self.pageImages[index]; pageContentViewController.titletext = self.pageTitles[index]; pageContentViewController.pageIndex = index; return pageContentViewController; } #pragma mark - Page View Controller Data Source -(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { NSUInteger index =((PageContentViewController *) viewController).pageIndex; if (index == NSNotFound) { return nil; } index--; if (index ==[self.pageTitles count]) { return nil; } return [self viewControllerAtIndex:index]; } - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { NSUInteger index = ((PageContentViewController*) viewController).pageIndex; if (index == NSNotFound) { return nil; } index++; if (index == [self.pageTitles count]) { return nil; } return [self viewControllerAtIndex:index]; } -(NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController{ return [self.pageTitles count]; } -(NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController { return 0; } @end // Second File PageViewController.h File #import <UIKit/UIKit.h> @interface PageContentViewController : UIViewController @property (strong, nonatomic) IBOutlet UILabel *txtLabel; @property (strong, nonatomic) IBOutlet UIImageView *backgroundImageView; @property NSUInteger pageIndex; @property NSString *titletext; @property NSString * imageFile; @end // SecondFile.M File #import "PageContentViewController.h" @interface PageContentViewController () @end @implementation PageContentViewController -(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self =[super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.backgroundImageView.image =[UIImage imageNamed:self.imageFile]; self.txtLabel.text =self.titletext; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end 

Xamarin / C#解决scheme

我在Xamarin中遇到了这个问题,这里是我的@micromanc3r解决scheme的版本:

 public class PageViewControllerDataSource : UIPageViewControllerDataSource { UIViewController[] pages; public PageViewControllerDataSource(UIViewController[] pages) { this.pages = pages; } 

  public override nint GetPresentationIndex(UIPageViewController pageViewController) { return Array.IndexOf(pages, pageViewController.ViewControllers[0]); } } 

确保在调用setViewControllers之前设置currentIndex