I am seeing different behavior between a UIPageViewController using Scroll transitions versus PageCurl. PageCurl works the way I expect but when using Scroll-ing I sometimes see extra (nonsensical) calls to viewControllerBeforeViewController: and viewControllerAfterViewController:
Does anyone recognize this pattern of extra Data Source calls?
I am displaying a series of images and I can start anywhere in the sequence.
When using the Scroll transition, but not PageCurl, after the initial page is displayed if I move to the "right", I get 3 DataSource calls instead of the single one I expect. For the example run below I began at my index value of 3. When I swipe to move to the "next" image I expect to get a single viewControllerAfterViewController: call on index 3 to get to index 4. If I run a test I get two extra calls: one for Before index 3 (i.e. 2) and one for After index 4 (i.e. 5). The output is:
2013-04-19 12:37:33.964 Clouds[496:907] Page 3 - viewControllerAfterViewController called on this index
2013-04-19 12:37:33.988 Clouds[496:907] Page 3 - viewControllerBeforeViewController called on this index
2013-04-19 12:37:34.010 Clouds[496:907] willTransitionToViewControllers to indices
2013-04-19 12:37:34.014 Clouds[496:907] Page 4
2013-04-19 12:37:34.461 Clouds[496:907] Page 4 - viewControllerAfterViewController called on this index
The view that is displayed after all this is indeed the view for index 4. After this first transition the UIPageViewController seems to behave the way I expect. When I use the PageCurl transition it always behaves the way I expect and I don't get any of these extraneous calls.
The code that actually produced the output is:
- (void)viewDidLoad
{
[super viewDidLoad];
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageViewController.delegate = self;
self.pageViewController.dataSource = self;
CloudImageVC *startingViewController = [self viewControllerAtIndex:self.currentPage storyboard:self.storyboard];
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
CGRect pageViewRect = self.view.bounds;
self.pageViewController.view.frame = pageViewRect;
[self.pageViewController didMoveToParentViewController:self];
// Add the page view controller's gesture recognizers to the book view controller's view so that the gestures are started more easily.
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
}
- (CloudImageVC *)viewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard *)storyboard {
// Return the data view controller for the given index.
if (index >= [self.imageNames count]) {
return nil;
}
self.dataViewController = [self makeDataViewControllerAtIndex:index storyboard:storyboard];
return self.dataViewController;
}
- (CloudImageVC *) makeDataViewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard *)storyboard {
// Make and return the data view controller for the given index.
if (index >= [self.imageNames count]) {
return nil;
}
// Create a new view controller and pass suitable data.
self.dataViewController = [storyboard instantiateViewControllerWithIdentifier:#"CloudImageVC"];
self.dataViewController.imageIndex = index;
//self.dataViewController.cloudImage = nil;
return self.dataViewController;
}
- (NSUInteger)indexOfViewController:(CloudImageVC *)viewController
{
// Return the index of the given data view controller.
// For simplicity, we store the index value in the view controller.
return viewController.imageIndex;
}
#pragma mark - Page View Controller Data Source
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSUInteger index = [self indexOfViewController:(CloudImageVC *)viewController];
NSLog(#"Page %d - viewControllerBeforeViewController called on this index", index);
if ((index == 0) || (index == NSNotFound)) {
return nil;
}
index--;
return [self viewControllerAtIndex:index storyboard:viewController.storyboard];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger index = [self indexOfViewController:(CloudImageVC *)viewController];
NSLog(#"Page %d - viewControllerAfterViewController called on this index", index);
if (index == NSNotFound) {
return nil;
}
index++;
if (index == self.imageNames.count) {
return nil;
}
return [self viewControllerAtIndex:index storyboard:viewController.storyboard];
}
#pragma mark - Protocol UI PageViewController Delegate
- (void) pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers {
NSLog(#"willTransitionToViewControllers to indices");
for (CloudImageVC *vc in pendingViewControllers) {
NSLog(#"Page %d",vc.imageIndex);
}
}
The answer is in the comment by rdelmar.
Related
I have a UIPageViewController in a container that is supposed to show, at minimum, three pages; at maximum, six. The number of pages would be determined by the user before the PageViewController appears.
For a bigger picture, I'm trying to create a project management application that allows for an agile ticket creating and management system. The PageVC is supposed to flip through 3 to 6 columns depending on how many the user wants to go along with that project. As an example, if it's a simple project, they can just have three columns named: "Unassigned", "Assigned", and "Complete". More complex projects could, for example, have 5 columns, named: "Backlog", "Issues", "In Progress", "Review", "Done". Each one of those columns would have its own ViewController within the PageVC.
This is what my data model looks like, to get an idea of where I get the number of columns from (Project attribute named: "projectColumnCount"):-
you can use following ObjectiveC concept in Swift.
It is Advisable to create a content view controller initially and then to use Pageviewcontroller Delegate Methods to create other controllers.
you can check following delegate Methods of Pageviewcontroller for same
Delegate Methods for Pageviewcontroller are as below.
- (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 == [arrPage count]) {
return nil;
}
return [self viewControllerAtIndex:index];
}
you can use below method to create instance of ContentVC
- (PageContentViewController *)viewControllerAtIndex:(NSUInteger)index
{
if (([arrPage count] == 0) || (index >= [arrPage
count])) {
return nil;
}
// Create a new view controller and pass suitable data.
pageContentViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageContentViewController"];
pageContentViewController.delagate = self;
pageContentViewController.pageIndex = index;
pageContentViewController.collselectedType = selectedType;
return pageContentViewController;
}
you can also Create Array of contentVC and can set that in Pageviewcontroller but it will consume more memory
you can set view conteollers array as below.
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
I've been struggling all weekend with this problem and have spent a long time googling to find the solution without any success.
My use case is pretty simple and I can't believe how difficult it is to make such a trivial behaviour work correctly.
My app is a simple paginated flow where users swipe left or right to see the next or previous page. I have a UIPageViewController and each page contains a UITableView. I have had problems trying to keep track of the page index inside the viewControllerAfterViewController and viewControllerBeforeViewController functions for the reasons explained here: PageViewController delegate functions called twice
I've tried following all the suggested workarounds for this problem (keeping track of the index inside willTransitionToViewControllers and didFinishAnimating) but this doesn't solve my problem as the viewController*ViewController functions must still return a viewController and since they are initially called twice, the first returned viewController seems to be the one that gets used and the second pass through doesn't seem to have any affect.
Although I've seen many questions and blogs about this problem, I haven't seen a single example that shows how to consistently return the correct viewController from the viewController*ViewController functions and would be massively grateful for an example. The main issue I can't see a solution to is how to determine the next index inside willTransitionToViewControllers if I only have a single viewController whose content is dynamically updated on page load. It seems like a chicken and egg problem to me; I need to figure out what content to update the page with, but to do that I need to know what the index of the page is (which is part of the content).
Edit
Here is a distilled version of the affected code:
- (void)viewDidLoad {
[super viewDidLoad];
_pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageViewController"];
_pageViewController.dataSource = self;
_pageViewController.delegate = self;
[self.view addSubview:_pageViewController.view];
PageContentViewController *startingPage = [self viewControllerAtIndex:0];
NSArray *viewControllers = #[startingPage];
[_pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
// Don't do any index calculations as the result is inconsistent
return [self viewControllerAtIndex:nextIndex];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
// Don't do any index calculations as the result is inconsistent
return [self viewControllerAtIndex:nextIndex];
}
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers {
// This value never changes because the global _pageViewContentController hasn't been updated yet
nextIndex = [((PageContentViewController *)pendingViewControllers[0]) pageIndex];
}
- (PageContentViewController *)viewControllerAtIndex:(NSUInteger)index {
_pageContentViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageContentViewController"];
_pageContentViewController.pageIndex = index;
_pageContentViewController.title = index;
return _pageContentViewController;
}
I've debugged the order in which these functions get called and would expect the global _pageViewContentController to be populated with the correct data after the page has transitioned.
Edit 2
To give some more detail on my problem; each of my pages contains a title and a table of web links. Clicking on a link opens a WebViewController to display the selected web page. With Yunus' solution below, everything displays correctly (the title and links appear as expected) but the problem comes when clicking on a link as this loads a link from the next page. It seems like the rendering phase of the page happens at the point the data is correct, but it then reinitialises the page content controller with incorrect data after rendering has finished which is why the actual link data is wrong (even though the rendered data is good).
Let's keep all the related contentViewControllers in an array
self.contentViewControllers = [NSMutableArray new];
for(int i=0; i< MAX_INDEX; i++) {
[self.contentViewControllers addObject:[self viewControllerAtIndex:0]];
}
Then what we need to do is to decide which view controller we should show on after and before methods
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerBeforeViewController:(UIViewController *)viewController
{
for(int i=0;i<self.contentViewControllers.count ;i++)
{
if(viewController == [self.contentViewControllers objectAtIndex:i])
{
if(i-1 >= 0)
{
return [self.contentViewControllers objectAtIndex:i-1];
}
}
}
return nil;
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerAfterViewController:(UIViewController *)viewController
{
for(int i=0;i<self.contentViewControllers.count ;i++)
{
if(viewController == [self.contentViewControllers objectAtIndex:i])
{
if(i+1 < self.contentViewControllers.count)
{
return [self.contentViewControllers objectAtIndex:i+1];
}
}
}
return nil;
}
Then in the transition method
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers
{
UIViewController* viewController = [pendingViewControllers objectAtIndex:0];
NSInteger nextIndex = [self.contentViewControllers indexOfObject:viewController];
[self.pageControl setCurrentPage:nextIndex];
}
I am new to iPad development. I know how to use images for Page view controller. My problem is i have 3 charts which i have done in three view controllers.. How can i combine all the view controllers in a single page view controller. I have for now kept three view controllers.
I have tried lot of tutorials but none explains me how to use three view controllers
I have done like this now but this is wrong
-(IBAction)handleSwipeLeft:(UISwipeGestureRecognizer*)sender {
LastLearningSessionViewController *last=[[LastLearningSessionViewController alloc]init];
[self presentViewController:last animated:YES completion:nil];
}
From what I can see it appears you may have done this slightly wrong.
First you need to create a controller for the UIPageViewController, that is a datasource and delegate.
Please note all code has been written directly to the answer and has not been tested.
MyUIPageViewController.h
#interface
MyUIPageViewController : UIViewController <UIPageViewControllerDataSource, UIPageViewControllerDelegate>
{
NSNumber *currentIndex //Using NSNumber to handle 32bit/64bit easier.
}
#property (nonatomic, strong) UIPageViewController *pageViewController
#property (nonatomic, strong) NSArray *controllersArray //Used to help navigate between controllers
#end
MyUIPageViewController.m
#import MyUIPageViewController.h
#implementation MyUIPageViewController
- (instancetype)initWithNibName:(NSString *)nibName
bundle:(NSBundle *)nibBundle
{
if(self = [super initWithNibName:nibName bundle:nibBundle])
{
//Create ChartViewController1 (UIViewController *ChartViewController1 = [[ChartViewController1Class alloc] init];)
//Create ChartViewController2
//Create ChartViewController3
//Now we have created all 3 chartViewControllers, create our controllers Array with the controller objects.
self.controllersArray = [[NSArray alloc] initWithObjects:ChartViewController1, ChartViewController2, ChartViewController3];
//Currently setting to 0. A proper way of handling with Multi-tasking is to store the index value from before, but not dealing with that right now.
currentIndex = [NSNumber numberWithInt:0];
//Create our PageViewController. Currently set to PageCurl and all pages will go from left to right.
//These options can be changed, if so desired (Scroll Effect like iBooks Textbooks and a page change from bottom to top like a flip book.
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
//Set ourselves as the datasource and delegate to handle the pages etc.
self.pageViewController.datasource = self;
self.pageViewController.delegate = self;
//We need to set the viewControllers for the PageViewController, because this is the initial load, we will not animate the change.
[self.pageViewController setViewControllers:self.controllersArray direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:^ (BOOL finished) {
//No animation is being done so no need to worry.
}];
//Set our view to be the pagecontroller's view, so we can see it all.
self.view = self.pageViewController.view;
}
return self;
}
//DataSource Methods:
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerBeforeViewController:(UIViewController *)viewController
{
//As this method looks for the previous view controller. If our current index is 0, there is no previous VC. But using the objectAtIndex method on the array would throw a outOfRange exception
if([self.currentIndex intValue] <= 0)
{
return nil;
}
else
{
return [self.controllersArray objectAtIndex:([self.currentIndex intValue] - 1)];
}
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerAfterViewController:(UIViewController *)viewController
{
//As this method looks for the next view controller. If our current index is the maximum value the array count and be (2), there isn't a new VC to push. But using the objectAtIndex method on the array would throw a outOfRange exception
if([self.currentIndex intValue] >= self.controllersArray.count)
{
return nil;
}
else
{
return [self.controllersArray objectAtIndex:([self.currentIndex intValue] + 1)];
}
}
//Delegate Methods
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
if(transitionCompleted)
{
//We will update our currentIndex, only if the transition has happened.
switch (previousViewControllers)
{
case 0:
//Something went wrong :S
break;
case 1:
//We are either in Vertical Orientation of the first viewController is only being shown.
if([pageViewController.viewControllers contains:[self.controllersArray objectAtIndex:([currentIndex intValue]+ 1)]])
{
currentIndex = [NSNumber numberWithInt:([currentIndex intValue] + 1)];
}
else
{
if([currentIndex intValue] == 0)
{
//Saftey Net.
}
else
{
currentIndex = [NSNumber numberWithInt:([currentIndex intValue] - 1)];
}
}
break;
case 2:
//We are in horizontal Orientation.
//With 3 View Controllers the only ViewController that will be in both arrays is the ViewController at index 1. We just need to see if the pageViewControllers viewcontrollers array contains the ViewController at index 0 or index 1.
if([pageViewController.viewControllers contains:[self.controllersArray objectAtIndex:([currentIndex intValue]+ 1)]])
{
currentIndex = [NSNumber numberWithInt:([currentIndex intValue] + 1)];
}
else
{
if([currentIndex intValue] == 0)
{
//Saftey Net.
}
else
{
currentIndex = [NSNumber numberWithInt:([currentIndex intValue] - 1)];
}
}
break;
default:
//Should never reach here.
break;
}
}
}
#end
It is also handy to look at the reference documentation:
Class Reference - Apple Docs
is there a way to programmatically tell when a certain page is showing in a pageviewcontroller? For example, I instantiated it as the following:
if (index == 0) {
pageContentViewController = [storyboard instantiateViewControllerWithIdentifier:#"OnCampusTable"];
}
else if (index == 1) {
pageContentViewController = [storyboard instantiateViewControllerWithIdentifier:#"OffCampusTable"];
}
else if (index == 2) {
pageContentViewController = [storyboard instantiateViewControllerWithIdentifier:#"MyEventsTable"];
}
I want to write something where
if (current page is "OnCampusTable") {
method 1
}
else if (current page is "OffCampusTable") {
method 2
}
else if (current page is "MyEventsTable") {
method 3
}
I've tried using the index, but because of the way that the pages load and stuff, it actually doesn't work properly. I was thinking of trying to access the page indicator thing (the little circle things) to get the page number, but I don't know how to do that.
I've seen a few solutions out there that use an array of ViewControllers and do comparisons, but I don't want to keep a bunch of controllers around (I generate them on the fly from my model), so I found a solution that seems to work.
Basically I point a property to the prior and next controllers in the data source before and after methods. In the delegate's didFinishAnimating call I compare the new controller to these properties to see if we moved forward or backward. One caveat is that before and after don't get called if the controller has already been loaded, so I reassign my property based on didFinishAnimating's previousViewController's value.
Note, I only implemented this for the case where one page is displayed.
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
if (self.pageIndex > 0) {
UIViewController *vc = [self genController:self.trackList[self.pageIndex - 1]];
self.priorVC = vc;
return vc;
} else {
self.priorVC = nil;
return nil;
}
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
if (self.pageIndex < self.trackList.count - 1) {
UIViewController *vc = [self genController:self.trackList[self.pageIndex + 1]];
self.nextVC = vc;
return vc;
} else {
self.nextVC = nil;
return nil;
}
}
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
if (finished && completed) {
if (pageViewController.viewControllers.lastObject == self.priorVC) {
NSLog(#"Back");
self.pageIndex--;
self.nextVC = previousViewControllers.lastObject;
} else if (pageViewController.viewControllers.lastObject == self.nextVC) {
NSLog(#"Forward");
self.pageIndex++;
self.priorVC = previousViewControllers.lastObject;
}
NSLog(#"Page: %ld",self.pageIndex);
}
}
You can use the delegate method pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted: to keep track of the current page and then execute some method depending on the page.
I'm trying to setup a UIPageViewController that can scroll infinitely by dynamically loading page views via an NSUrlConnection data pull. I start with 3 views: prev,curr,next; and load an additional view when the first or last view in the pageData array is reached.
The trouble is that I load the additional views in viewControllerBeforeViewController or viewControllerAfterViewController. It seems that these methods can be called 2-3 times when doing a single swipe between pages. They can also be called during a half-swipe that never finishes the page transition. This can mean that multiple preloads start getting done prematurely. Then somehow the pageViewController forgets the current location.
[self.pageViewController setViewControllers:#[[self.pageData objectAtIndex:gotoIdx]] direction:direction animated:NO completion:nil];
This line is used below to signal an addition of data in the pageViewController, and to go to eh appropriate view. When I start using it, instead of going to the prev/next view with a swipe, it starts jumping to seemingly random views. Once I started going forward when swiping backwards...
Is there a more appropriate place to do the preload that is only called once after the page transition completes? And, does the line above have to be called, or is there a more reliable way to ensure it goes to the correct page? Feeling frustrated trying to wire this up here.
// the init line, somewhere early on. uses Scoll style
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationVertical options:nil];
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSUInteger index = [self.pageData indexOfObject:viewController];
if(index == 1){
// if loading last one on start, preload one more in advance
[self loadSecondaryCalData:-1 endView:[[self viewControllerAtIndex:index-1] retain]];
} else if ((index == 0) || (index == NSNotFound)) {
return nil;
}
index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger index = [self.pageData indexOfObject:viewController];
if(index == [self.pageData count]-2){
[self loadSecondaryCalData:1 endView:[[self viewControllerAtIndex:index+1] retain]]; // if last one, preload one more in advance
} else if (index == NSNotFound) {
return nil;
}
index++;
if (index == [self.pageData count]) {
return nil;
}
return [self viewControllerAtIndex:index];
}
- (void)loadSecondaryCalData:(int)howMany endView:(CalendarViewController*)endView {
// initiate NSURLConnection async request for view data
}
- (void)loadSecondaryCals: (NSDictionary*)data {
// callback for async request
// ... process view, cal
// add new object to page data, at start or end
if(next){
[self.pageData addObject:cal];
gotoIdx = [self.pageData count]-2;
direction = UIPageViewControllerNavigationDirectionForward;
} else {
[self.pageData insertObject:cal atIndex:0];
gotoIdx = 1;
direction = UIPageViewControllerNavigationDirectionReverse;
}
[self.pageViewController setViewControllers:#[[self.pageData objectAtIndex:gotoIdx]] direction:direction animated:NO completion:nil];
// alternate method to above line
/*
__block CalendarPageViewViewController *blocksafeSelf = self;
__block int blocksafeGotoIdx = gotoIdx;
__block UIPageViewControllerNavigationDirection blocksafeDirection = direction;
[self.pageViewController setViewControllers:#[[self.pageData objectAtIndex:gotoIdx]] direction:direction animated:YES completion:^(BOOL finished){
if(finished)
{
dispatch_async(dispatch_get_main_queue(), ^{
[blocksafeSelf.pageViewController setViewControllers:#[[blocksafeSelf.pageData objectAtIndex:blocksafeGotoIdx]] direction:blocksafeDirection animated:NO completion:nil];
});
}
}];
*/
}
UPDATE:
Thanks to the fast response below, referencing a great function I wasn't aware of. Here's the preload method that so perfectly only gets called once on completion of the transition. This seems to have greatly cleared up the unreliable jumping around of views and forgetting of location. Thanks #sha!
// function to detect if we've reached the first or last item in views
// detects for full completion only
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
if(completed == TRUE && [previousViewControllers count] > 0 && [pageData count] > 1){
CalendarViewController *firstCal = [pageData objectAtIndex:0];
CalendarViewController *lastCal = [pageData objectAtIndex:([pageData count]-1)];
CalendarViewController *prevCal = [previousViewControllers objectAtIndex:0];
CalendarViewController *currCal = [[pageViewController viewControllers] objectAtIndex:0];
NSLog(#"transition completed: %# -> %#", prevCal.week_day_date, currCal.week_day_date);
if(currCal == firstCal){
// preload on begining
[self loadSecondaryCalData:-1 endView:firstCal];
} else if(currCal == lastCal){
// preload to end
[self loadSecondaryCalData:1 endView:lastCal];
}
}
}
I think you need to do your loading calls inside pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted: handler. This method will be called when animation has finished and new ViewController became an active one.