【问题标题】:Changing UIPageViewController's page programmatically doesn't update the UIPageControl以编程方式更改 UIPageViewController 的页面不会更新 UIPageControl
【发布时间】:2014-04-28 14:11:21
【问题描述】:

在我的自定义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

- (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 做到这一点,我会尝试自己制作。但是,如果这是可能的,那就太好了!

【问题讨论】:

标签: ios iphone cocoa-touch


【解决方案1】:

要更新您的 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;
}

希望这能解决您的问题。 :)

【讨论】:

  • 谢谢,我试试这个!
  • 这将如何工作? currentIndex 是实例 var,如果是,为什么要在 scrollToNext 中声明它?
  • 注意:在调用 setViewController 之前更新 currentIndex 很重要:... 反过来对我不起作用
  • 感谢您的解决方案,它帮助我编写了 Swift 3.0 中的代码
【解决方案2】:

如已接受的答案中所述,您需要实施

- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController

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

目标-C:

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

Swift 3+:

func presentationIndex(for pageViewController: UIPageViewController) -> Int {
        guard let index = viewControllers?.index(of: (pageViewController.viewControllers?.first)!) else { return 0 }
        return index
}

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

【讨论】:

  • 这是最简单、最简单的解决方案。下面包括一个 Xamarin 解决方案。
【解决方案3】:

Xamarin/C# 解决方案

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

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]);
    }
}

【讨论】:

    【解决方案4】:

    SWIFT 4.2

    func presentationIndex(for pageViewController: UIPageViewController) -> Int {
        guard let currentController = pageViewController.viewControllers?.first else { 
         return 0 }
        guard let index = viewControllerList.index(of: currentController) else { return 0 }
        return index
    }
    

    【讨论】:

      【解决方案5】:

      如果实现了这两种方法,页面指示器将可见,转换样式为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。否则它将无法正常工作。

      【讨论】:

        【解决方案6】:
        // 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
        

        【讨论】:

          【解决方案7】:

          确保在调用 setViewControllers 之前设置 currentIndex

          【讨论】:

            猜你喜欢
            • 2013-02-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-07-22
            相关资源
            最近更新 更多