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

时间:2014-03-21 09:30:11

标签: ios iphone cocoa-touch

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

如果我不能使用属于"属于的UIPageControl"到我的UIPageViewController我会尝试自己制作。但如果可能的话,那就太好了!

7 个答案:

答案 0 :(得分:27)

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

-(NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController

此方法负责更新页面控件指示符(当您使用UIPageViewController时)。您只需要在此方法中返回当前页面值。在自定义UIPageViewController上使用/调用setViewControllers时,默认情况下会调用Method。

因此,您需要编写的代码块是:

- (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;
}

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

答案 1 :(得分:7)

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

- (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在给定NSArray中显示的UIViewControllers UIPageViewController的位置。我不确定你的BSTCMWelcomingPageViewModel是如何工作的,但它应该很容易调整。

答案 2 :(得分:2)

Xamarin / C#Solution

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

答案 3 :(得分:0)

如果两种方法都已实施,转化方式为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。否则它就不会起作用。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

确保在调用setViewControllers

之前设置currentIndex

答案 6 :(得分:0)

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
}