It\'s odd that there\'s no straightforward way to do this. Consider the following scenario:
Actually I think I solved the issue. This is what was happening in my app:
I am just learning this myself, so take with a grain of salt, but from what I understand, you need to change the datasource of the pageviewcontroller, not remove the viewcontroller. How many pages are shown in a pageviewcontroller is determined by its datasource, not the viewcontrollers.
This problem exists when you are trying to change viewControllers during swipe gesture animation between viewControllers. To solve this problem, i made a simple flag to discover when page view controller is during transition.
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers {
self.pageViewControllerTransitionInProgress = YES;
}
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
self.pageViewControllerTransitionInProgress = NO;
}
And when i am trying to chenge view controller i am checking if there is transition in progress.
- (void)setCurrentPage:(NSString *)newCurrentPageId animated:(BOOL)animated {
if (self.pageViewControllerTransitionInProgress) {
return;
}
[self.pageContentViewController setViewControllers:@[pageDetails] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:^(BOOL finished) {
}
}
maq is right. If you are using the scrolling transition, removing a child view controller from the UIPageViewController does not prevent the deleted "page" from returning on-screen if the user navigates to it. If you're interested, here's how I removed the child view controller from the UIPageViewController.
// deleteVC is a child view controller of the UIPageViewController
[deleteVC willMoveToParentViewController:nil];
[deleteVC.view removeFromSuperview];
[deleteVC removeFromParentViewController];
View controller deleteVC is removed from the childViewControllers property of the UIPageViewController, but still appears on-screen if the user navigates to it.
Until someone smarter than me finds an elegant solution, here's a work around (it's a hack--so you have to ask yourself if you really need to remove pages from a UIPageViewController).
These instructions assume that only one page is displayed at a time.
After the user taps a button indicating that she would like to delete the page, navigate to the next or previous page using the setViewControllers:direction:animated:completion: method. Of course, you then need to delete the page's content from your data model.
Next (and here's the hack), create and configure a brand new UIPageViewController and load it in the foreground (i.e., in front of the other UIPageViewController). Make sure that the new UIPageViewController starts off displaying the exact same page that was previously displayed. Your new UIPageViewController will fetch fresh view controllers from the data source.
Finally, unload and destroy the UIPageViewController that's in the background.
Anyway, maq asked a really good question. Unfortunately, I don't have enough reputation points to up vote the question. Ah, dare to dream... someday I will have 15 reputation points.
Concluding Matt Mc's great answer, the following method could be added to a subclass of UIPageViewController, that way allowing the usage of setViewControllers:direction:animated:completion: as it was intended to be used if the bug would not be present.
- (void) setViewControllers:(NSArray*)viewControllers direction:(UIPageViewControllerNavigationDirection)direction animated:(BOOL)animated completion:(void (^)(BOOL))completion {
if (!animated) {
[super setViewControllers:viewControllers direction:direction animated:NO completion:completion];
return;
}
[super setViewControllers:viewControllers direction:direction animated:YES completion:^(BOOL finished){
if (finished) {
dispatch_async(dispatch_get_main_queue(), ^{
[super setViewControllers:viewControllers direction:direction animated:NO completion:completion];
});
} else {
if (completion != NULL) {
completion(finished);
}
}
}];
}
Now, simply call setViewControllers:direction:animated:completion: on the class/subclasses implementing this method, and it should work as expected.
we are getting crash on tab change .So one solution i got is didChangeSelect of tabs disable the userintraction.