I know that there are several other questions like this, but i couldn't find a solution for my problem. I use a pageViewController which displays different ViewControllers. Every time the pageViewController moves forward I check the input of the lastPage. If it's wrong the pageViewController should go back to that page by using the setViewController method. Without this method everything works fine but if I try to use it the app crashes with the following exception:
19:48:25.596 Phook[23579:60b] *** Assertion failure in -[_UIQueuingScrollView _replaceViews:updatingContents:adjustContentInsets:animated:], /SourceCache/UIKit_Sim/UIKit-2935.137/_UIQueuingScrollView.m:383
2014-06-02 19:48:25.600 Phook[23579:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: [views count] == 3'
And here's my code:
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished
previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
if (completed && finished)
{
RegisterUserPageContent* lastPage = (RegisterUserPageContent*)previousViewControllers[ previousViewControllers.count-1];
int lastIndex = lastPage.pageIndex;
int newIndex = ((RegisterUserPageContent*)[self.pageViewController.viewControllers objectAtIndex:0]).pageIndex;
if (newIndex > lastIndex)
{ // Moved Forward
if(!lastPage.testInput)
{
[self.pageViewController setViewControllers:@[ [self.storyboard instantiateViewControllerWithIdentifier:_pageStoryBoardIDs[0]] ]
direction:UIPageViewControllerNavigationDirectionReverse
animated:YES completion:nil];
}
}
else
{ // Moved Reverse
}
}
}
As I already said. I searched a lot and implemented some solutions but nothing helped. Thanks.
I ran into the same problem, and was able to solve it using a tip from this answer https://stackoverflow.com/a/20973822/3757370. Simply placing the setViewControllers:direction:animated:completion: code inside of a dispatch_async block on the main queue fixed it for me. For you this would look like
dispatch_async(dispatch_get_main_queue(), ^{
[self.pageViewController setViewControllers:@[ [self.storyboard instantiateViewControllerWithIdentifier:_pageStoryBoardIDs[0]] ]
direction:UIPageViewControllerNavigationDirectionReverse
animated:YES completion:nil];
});
Hope it helps!
Ran into this exact same issue. Solved it by setting the first content controller explicitly on the UIPageViewController when it is first loaded (ie: inside 'viewDidLoad').
// create first page
UIViewController* firstContentPageController = [self contentControllerAtIndex: 0];
[_paginationController
setViewControllers: @[firstContentPageController]
direction: UIPageViewControllerNavigationDirectionForward
animated: NO
completion: nil];
where 'contentControllerAtIndex:' is a simple helper method that creates a content controller. I also use it within the two delegate methods in order to return the appropriate controller for a given page.
- (UIViewController*)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSInteger index = (NSInteger)((MyContentController*)viewController).pageIndex;
return [self contentControllerAtIndex: index - 1];
}
- (UIViewController*)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSInteger index = (NSInteger)((MyContentController*)viewController).pageIndex;
return [self contentControllerAtIndex: index + 1];
}
- (MyContentController*)contentControllerAtIndex: (NSInteger)index {
if (index < 0 || _pagesContent.count <= index)
return nil;
// create view controller
MyContentController* contentController = [self.storyboard instantiateViewControllerWithIdentifier: @"MyContentController"];
contentController.pageIndex = index;
contentController.content = [_pagesContent objectAtIndex: index];
return contentController;
}
The reason for this is that the UIPageViewControllerDataSource protocol was designed to only have methods for pulling the previous/next content controller, as opposed to pulling a single controller at a particular index. It's an odd design decision, but the caveat is that instead of being called by Cocoa when the component is first loaded you have to manually set its starting state. Poor framework design here IMHO.
Well it's 2018 and the bug is still around. I tried all the solutions above, but none worked for me. And after many tries, setting the animation parameter to false, was what worked for me in swift 4
let myViewController : UIViewController = orderedViewControllers[vcIndex]
setViewControllers([myViewController], direction: .forward, animated: false, completion: nil);
Then it was just a matter of setting a custom transition. Hope it helps others in the same situation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With