UIPageViewController index is not working properly - ios

Basically, I am making a page app, which use UIPageViewController. When the user scrolls the page, they can see different content. The problem now is, when I scroll the page, the first and second page works properly, and the index is correct. But when I scroll to the third page, the index keeps at "1", and don't change afterwards. And the other page keeps the appearance of the second page, whose index is "1".
I was following the tutorial: http://www.appcoda.com/uipageviewcontroller-storyboard-tutorial/
My code:
View Controller.h
#import <UIKit/UIKit.h>
#import "PageContentViewController.h"
#import "PageViewController.h"
#interface ViewController : UIViewController<UIPageViewControllerDataSource, UIPageViewControllerDelegate>
#property (strong, nonatomic) PageViewController *pageViewController;
#property (strong, nonatomic) NSArray *pageTitles;
#end
View Controller.m:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.pageTitles = #[#"First Page", #"Second Page", #"Third Page"];
self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageViewController"];
self.pageViewController.dataSource = self;
if ([self.pageTitles count])
{
PageContentViewController *startingViewController = [self viewControllerAtIndex: 0];
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
}
}
- (PageContentViewController *) viewControllerAtIndex: (NSUInteger)index{
if (index < [self.pageTitles count])
{
PageContentViewController *pageContentViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageContentViewController"];
pageContentViewController.titleText = self.pageTitles[index];
NSLog(#"%li", index);
UIColor *backgroundColor;
switch (index) {
case 0:
backgroundColor = [UIColor greenColor];
break;
case 1:
backgroundColor = [UIColor blueColor];
break;
case 2:
backgroundColor = [UIColor purpleColor];
break;
default:
break;
}
pageContentViewController.backgroundColor = backgroundColor;
return pageContentViewController;
}
return nil;
}
- (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];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger index = ((PageContentViewController *)viewController).pageIndex;
if (index == 0 || index == NSNotFound)
{
return nil;
}
index--;
return [self viewControllerAtIndex:index];
}
- (NSInteger) presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
return [self.pageTitles count];
}
- (NSInteger) presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
return 0;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Page Content View Controller.h
#import <UIKit/UIKit.h>
#interface PageContentViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIView *backgroundView;
#property (weak, nonatomic) IBOutlet UILabel *titleLable;
#property (nonatomic) NSUInteger pageIndex;
#property (strong, nonatomic) NSString *titleText;
#property (strong, nonatomic) UIColor *backgroundColor;
#end
Page Content View Controller.m
#import "PageContentViewController.h"
#interface PageContentViewController ()
#end
#implementation PageContentViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.titleLable.text = self.titleText;
[self.backgroundView setBackgroundColor:self.backgroundColor];
}
- (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

In viewControllerAtIndex:, you need to set the value of pageIndex property of the pageContentViewController:
pageContentViewController.pageIndex = index;

Related

Unrecognized Selector Issue in PageViewController

I am making simple intro screen. the screen slides on swipe but I want also swipe the intro screens with button tap but when I tap next button it shows an error.
complete code
#import <UIKit/UIKit.h>
#import "WalkthroughPageViewController.h"
#interface WalkthroughContentViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *pageLbl;
#property (weak, nonatomic) IBOutlet UIButton *nextBtn;
#property(strong,nonatomic)WalkthroughPageViewController *pageVC;
#property NSUInteger index;
#property NSString *heading;
#end
WalkthroughContentViewController.m
#import "WalkthroughContentViewController.h"
#interface WalkthroughContentViewController ()
#end
#implementation WalkthroughContentViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.pageLbl.text = self.heading;
switch (self.index) {
case 0:
case 1:
[self.nextBtn setTitle:#"Next" forState:UIControlStateNormal];
break;
case 2:
[self.nextBtn setTitle:#"Done" forState:UIControlStateNormal];
break;
default:
break;
}
}
- (IBAction)nextBtn:(id)sender {
switch (self.index) {
case 0:
case 1:
self.pageVC = ((WalkthroughPageViewController*)self.parentViewController);
[self.pageVC forward:self.index];
break;
case 2:
[self performSegueWithIdentifier:#"LoginScreen" sender:nil];
break;
default:
break;
}
}
#end
WalkthroughPageViewController.h
#import <UIKit/UIKit.h>
#interface WalkthroughPageViewController :UIPageViewController<UIPageViewControllerDataSource>
#property (strong, nonatomic) UIPageViewController *pageViewController;
#property NSArray *pageHeading;
-(void)forward:(NSUInteger)index;
#end
WalkthroughPageViewController.m
#import "WalkthroughPageViewController.h"
#import "WalkthroughContentViewController.h"
#interface WalkthroughPageViewController ()
#end
#implementation WalkthroughPageViewController
NSUInteger indexP;
- (void)viewDidLoad {
[super viewDidLoad];
self.pageHeading = #[#"page1",#"page2",#"page3"];
self.pageViewController = [[UIPageViewController alloc] init];
self.pageViewController.dataSource = self;
WalkthroughContentViewController *startingViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = #[startingViewController];
[_pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
indexP = ((WalkthroughContentViewController*) viewController).index;
if ((indexP == 0) || (indexP == NSNotFound)) {
return nil;
}
indexP--;
return [self viewControllerAtIndex:indexP];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
indexP = ((WalkthroughContentViewController*) viewController).index;
if (indexP == NSNotFound) {
return nil;
}
indexP++;
if (indexP == [self.pageHeading count]) {
return nil;
}
return [self viewControllerAtIndex:indexP];
}
- (WalkthroughContentViewController *)viewControllerAtIndex:(NSUInteger)index
{
if ((index == NSNotFound) || (index >= [self.pageHeading count])) {
return nil;
}
// Create a new view controller and pass suitable data.
WalkthroughContentViewController *pageContentViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"WalkthroughContentViewController"];
pageContentViewController.heading = self.pageHeading[index];
pageContentViewController.index = index;
return pageContentViewController;
}
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
return [self.pageHeading count];
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
return 0;
}
-(void)forward:(NSUInteger)index{
[self.pageViewController setViewControllers:#[[self viewControllerAtIndex:index]] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
}
#end
**Error:: **
[UIPageViewController forward:]: unrecognized selector sent to instance

UIPageViewController with static content

I want to put some static content (buttons, views etc) on UIPageViewController. But I don't know how.
Any ideas?
Just create a container uiviewcontroller that will have e.g. a static button and an empty uiview. Create them as iboutlets and a usual property UIPageViewController called pvc. Then you can create a pvc in code and add it to the uiview outlet via addSubview:.
This is some code copied from a project i did last weeek. There are Skidata in a UIPageViewController and put an UIImage of a snowflake as overlay about it. I copied only the relevant parts of code. Hope this will help you:
SkiViewController.m
#interface SkiViewController () <UIPageViewControllerDataSource>
#property (strong, nonatomic) UIPageViewController *pageController;
#property (strong, nonatomic) SkiDataArray* skiDataArray;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (weak, nonatomic) IBOutlet UIView *pageDataView;
#end
#implementation SkiViewController
- (SkiSubViewController *)viewControllerAtIndex:(NSUInteger)index
{
SkiSubViewController *childViewController = [[SkiSubViewController alloc] initWithNibName:#"SkiSubViewController" bundle:nil];
childViewController.indexNumber = index;
if(self.skiDataArray)
{
childViewController.skiData = self.skiDataArray[index];
}
return childViewController;
}
#pragma mark - lify cycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageController.dataSource = self;
[self addPageControllerViewControllers];
[self addPageControllerView];
[self addChildViewController:self.pageController];
[self.pageController didMoveToParentViewController:self];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self updateData]; // download ski data and stuff
}
- (void)addPageControllerViewControllers
{
SkiSubViewController *viewController = [self viewControllerAtIndex:0];
if(self.skiDataArray)
{
viewController.skiData = self.skiDataArray[0];
}
[self.pageController setViewControllers:#[viewController] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
}
- (void)addPageControllerView
{
self.pageController.view.translatesAutoresizingMaskIntoConstraints = NO; // avoids conflicts with auto generated constraints
[self.pageDataView addSubview:self.pageController.view];
NSDictionary *views = #{ #"subview": self.pageController.view };
[self.pageDataView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[subview]|" options:0 metrics: 0 views:views]];
[self.pageDataView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[subview]|" options:0 metrics: 0 views:views]];
[self.pageDataView updateConstraintsIfNeeded];
}
#pragma mark - uipageviewcontroller data source
- (UIViewController*)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger index = [(SkiSubViewController *)viewController indexNumber];
if (index == 0)
{
return nil;
}
else
{
index--;
return [self viewControllerAtIndex:index];
}
}
- (UIViewController*)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger index = ((SkiSubViewController *)viewController).indexNumber;
index++;
if (index == self.skiDataArray.count)
{
return nil;
}
else
{
return [self viewControllerAtIndex:index];
}
}
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
return self.skiDataArray.count;
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
return 0;
}
#end
SkiSubViewController.h
#interface SkiSubViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (assign, nonatomic) NSInteger indexNumber;
#property (strong, nonatomic) SkiData* skiData;
#end
SkiSubViewController.m
#interface SkiSubViewController ()
#property (weak, nonatomic) IBOutlet UILabel *label;
#end
#implementation SkiSubViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.label.text = [NSString stringWithFormat:#"Number %li", (long)self.indexNumber];
}
#end

Creating a new interface in iOS App xcode

Good morning,
I'm trying to create a new interface for implementing a Page View Controller but I'm doing something wrong because it's not working. I hope someone can see the error and help me with that because I'm a little bit stuck on this problem.
http://autograpp.com/Main.jpg
aupViewController.m
#import "aupViewController.h"
#import <FacebookSDK/FacebookSDK.h>
#import "SBJson.h"
#interface TutorialViewController ()
#end
#implementation TutorialViewController
- (void)viewDidLoad
{
// Create the data model
_pageTitles = #[#"Over 200 Tips and Tricks", #"Discover Hidden Features", #"Bookmark Favorite Tip", #"Free Regular Update"];
_pageImages = #[#"page1.png", #"page2.png", #"page3.png", #"page4.png"];
// Create page view controller
self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageViewController"];
self.pageViewController.dataSource = self;
PageContentViewController *startingViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
// Change the size of page view controller
self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 30);
[self addChildViewController:_pageViewController];
[self.view addSubview:_pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (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 == 0) || (index == NSNotFound)) {
return nil;
}
index--;
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
aupViewController.h
#import <UIKit/UIKit.h>
#import <FacebookSDK/FacebookSDK.h>
#import "PageContentViewController.h"
#interface TutorialViewController : UIViewController <UIPageViewControllerDataSource>
- (IBAction)startWalkthrough:(id)sender;
#property (strong, nonatomic) UIPageViewController *pageViewController;
#property (strong, nonatomic) NSArray *pageTitles;
#property (strong, nonatomic) NSArray *pageImages;
#end
#interface aupViewController : UIViewController <FBLoginViewDelegate>
#property (weak, nonatomic) IBOutlet FBLoginView *loginButton;
#property (weak, nonatomic) IBOutlet UITextField *txtUsername;
#property (weak, nonatomic) IBOutlet UITextField *txtPassword;
- (IBAction)loginClicked:(id)sender;
- (IBAction)backgroundClick:(id)sender;
- (IBAction)textFieldReturn:(id)sender;
#end
#interface LoginViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *txtUsername;
#property (weak, nonatomic) IBOutlet UITextField *txtPassword;
#property (weak, nonatomic) IBOutlet UITextField *txtMail;
- (IBAction)registerClicked:(id)sender;
- (IBAction)backgroundClick:(id)sender;
- (IBAction)textFieldReturn:(id)sender;
#end
#interface MainViewController : UIViewController
#end
PageContentViewController.h
#import <UIKit/UIKit.h>
#interface PageContentViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *backgroundImageView;
#property (weak, nonatomic) IBOutlet UILabel *titleLabel;
#property NSUInteger pageIndex;
#property NSString *titleText;
#property NSString *imageFile;
#end
PageContentViewController.m
#import "PageContentViewController.h"
#interface PageContentViewController ()
#end
#implementation PageContentViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.backgroundImageView.image = [UIImage imageNamed:self.imageFile];
self.titleLabel.text = self.titleText;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
But I'm getting the error:
Cannot find interface declaration for TutorialViewController, did you mean LoginViewController?
And why is this not working? I really appreciate your help.
Thanks in advance.
The problem is that I had the wrong path in one of my files. I correct it and now everything is working. Thanks for your help.

UIPageViewController with array of programatically generated views

So i need to create a UIPageViewController that shows a few views (1-25). Basically i have a quiz app, and for every wrong question i save the question number (1-25) in a NSMutableArray. After the quiz is done i want to show the user which quiz answer was wrong. I have the methods that sets the view of the wrong answers (same methods i use to set the views in the quiz).
This keeps giving me 'Thread1:' errors.
PVCPagesViewController.h
#import <UIKit/UIKit.h>
#import "PVCContentViewController.h"
#interface PVCPagesViewController : UIViewController <UIPageViewControllerDataSource, UIPageViewControllerDelegate>
#property (weak, nonatomic) IBOutlet UIPageControl *pageControl;
#end
.
PVCPagesViewController.m
#import "PVCPagesViewController.h"
#interface PVCPagesViewController () {
NSArray *pages;
}
#property (retain, nonatomic) NSArray *pages;
#property (strong, nonatomic) UIPageViewController *pageController;
#end
#implementation PVCPagesViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//I think my problem is around here?
PVCContentViewController *page1 = [[PVCContentViewController alloc] init];
[page1 example1];
PVCContentViewController *page2 = [[PVCContentViewController alloc] init];
[page1 example2];
PVCContentViewController *page3 = [[PVCContentViewController alloc] init];
[page1 example3];
PVCContentViewController *page4 = [[PVCContentViewController alloc] init];
[page1 example2];
// load the view controllers in our pages array
self.pages = [[NSArray alloc] initWithObjects:page1, page2, page3, page4, nil];
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
[self.pageController setDelegate:self];
[self.pageController setDataSource:self];
[[self.pageController view] setFrame:[[self view] bounds]];
NSArray *viewControllers = [NSArray arrayWithObject:[self.pages objectAtIndex:0]];
[self.pageControl setCurrentPage:0];
[self.pageControl addTarget:self action:#selector(changePage:) forControlEvents:UIControlEventValueChanged];
[self.pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
[self addChildViewController:self.pageController];
[self.view addSubview:self.pageControl];
[[self view] addSubview:[self.pageController view]];
[self.pageController didMoveToParentViewController:self];
[self.view sendSubviewToBack:[self.pageController view]];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger currentIndex = [self.pages indexOfObject:viewController]; // get the index of the current view controller on display
[self.pageControl setCurrentPage:self.pageControl.currentPage+1]; // move the pageControl indicator to the next page
// check if we are at the end and decide if we need to present the next viewcontroller
if ( currentIndex < [self.pages count]-1) {
return [self.pages objectAtIndex:currentIndex+1]; // return the next view controller
} else {
return nil; // do nothing
}
}
- (UIViewController *) pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSUInteger currentIndex = [self.pages indexOfObject:viewController]; // get the index of the current view controller on display
[self.pageControl setCurrentPage:self.pageControl.currentPage-1]; // move the pageControl indicator to the next page
// check if we are at the beginning and decide if we need to present the previous viewcontroller
if ( currentIndex > 0) {
return [self.pages objectAtIndex:currentIndex-1]; // return the previous viewcontroller
} else {
return nil; // do nothing
}
}
- (void)changePage:(id)sender {
UIViewController *visibleViewController = self.pageController.viewControllers[0];
NSUInteger currentIndex = [self.pages indexOfObject:visibleViewController];
NSArray *viewControllers = [NSArray arrayWithObject:[self.pages objectAtIndex:self.pageControl.currentPage]];
if (self.pageControl.currentPage > currentIndex) {
[self.pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
} else {
[self.pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil];
}
}
#end
.
PVCContentViewController.h
#import <UIKit/UIKit.h>
#import "PVCPagesViewController.h"
#interface PVCContentViewController : UIPageViewController
#property (weak, nonatomic) IBOutlet UILabel *label1;
#property (weak, nonatomic) IBOutlet UILabel *label2;
#property (weak, nonatomic) IBOutlet UILabel *label3;
-(void)example1;
-(void)example2;
-(void)example3;
#end
And lastly:
PVCContentViewController.m
#import "PVCContentViewController.h"
#interface PVCContentViewController ()
#end
#implementation PVCContentViewController
#synthesize label3,label2,label1;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (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.
}
*/
-(void)example1{
label1.text = #"View 1";
label2.text = #"View 1";
label3.text = #"view 1";
}
-(void)example2{
label1.text = #"View 2";
label2.text = #"View 2";
label3.text = #"view 2";
}
-(void)example3{
label1.text = #"View 3";
label2.text = #"View 3";
label3.text = #"view 3";
}
#end
I have borrowed the start source code from here:
https://github.com/hackin247/UIPageViewController
My source code:
https://github.com/4FunAndProfit/UIPageViewControllerHelp
Please let me know if you need anymore info!
Have you tried setting the pageController with the self.pages array directly?
[self.pageController setViewControllers:pages direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
I don't see the point of creating yet another array(viewControllers). Maybe this is causing issues when trying to get the next page since the pageController only has a single viewController ([self.pages objectAtIndex:0]) but the "data source" says it should have more based on the self.pages.count.

Changing UIPageViewController's page programmatically doesn't update the UIPageControl

In my custom UIPageViewController class:
- (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;
}
Then I programmatically set the current ViewController when a button is hit:
- (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];
}
}
If I can't do this with the UIPageControl that "belongs" to my UIPageViewController I will just try to make my own. But it would be nice if this was possible tho!
to update your UIPageControl indicator, you need to implement one data source method of UIPageViewController (the UIPageViewControllerDataSource method) :
-(NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
This method is responsible for updating the page control indicator (when you use UIPageViewController). You only need to return the currentpage value in this method. The Method gets called by default when you use/make a call for setViewControllers on your custom UIPageViewController.
So the chunk of code that you need to write is:
- (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;
}
Hope this solves your problem. :)
As mentioned in accepted answer, you need to implement
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
But for me it was enough to use it like this:
Objective-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
}
Without the need to remember the current index. Where self.controllers is an NSArray of UIViewControllers displayed in given UIPageViewController. I'm not sure how exactly your BSTCMWelcomingPageViewModel works, but it should be easy to adjust.
Xamarin/C# Solution
I had this problem in Xamarin, here is my version of #micromanc3r's solution:
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]);
}
}
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
}
A page indicator will be visible if both methods are implemented, transition style is UIPageViewControllerTransitionStyleScroll and navigation orientation is UIPageViewControllerNavigationOrientationHorizontal. Both methods are called in response to a setViewControllers:... call, but the presentation index is updated automatically in the case of gesture-driven navigation.
(NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController NS_AVAILABLE_IOS(6_0);: The number of items reflected in the page indicator.
(NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController NS_AVAILABLE_IOS(6_0);: The selected item reflected in the page indicator.
The answer above, given by aansul, works.
Note : Don't forget to set the pageViewController's Transition style to Scroll instead of Page Curl. Otherwise it won't work.
// 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
Make sure to set the currentIndex BEFORE you call setViewControllers

Resources