I m using UIPageViewController
on iPad where I need to show a firstviewController
in the first page and ContentViewController
in the next page in landscape.
If I set the NSArray
with two viewControllers
the app is crashes at [self.pagviewController setViewController:]
with the following exception:
The number of provided view controllers (2) doesn't match the number required (1) for the requested spine location (UIPageViewControllerSpineLocationMin)
Below is the code:
#pragma mark - UIPageViewControllerDataSource Methods - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { NSUInteger currentIndex = [self.modelArray indexOfObject:[(ContentViewController *)viewController textContents]]; if(currentIndex == 0) { return nil; } ContentViewController *contentViewController = [[ContentViewController alloc] init]; contentViewController.textContents = [self.modelArray objectAtIndex:currentIndex - 1]; return contentViewController; } - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { NSUInteger currentIndex = [self.modelArray indexOfObject:[(ContentViewController *)viewController textContents]]; if(currentIndex == self.modelArray.count-1) { return nil; } ContentViewController *contentViewController = [[ContentViewController alloc] init]; contentViewController.textContents = [self.modelArray objectAtIndex:currentIndex + 1]; return contentViewController; } //#pragma mark - UIPageViewControllerDelegate Methods - (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation { if(UIInterfaceOrientationIsPortrait(orientation)) { //Set the array with only 1 view controller UIViewController *currentViewController = [self.pageViewController.viewControllers objectAtIndex:0]; NSArray *viewControllers = [NSArray arrayWithObject:currentViewController]; [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL]; //Important- Set the doubleSided property to NO. self.pageViewController.doubleSided = NO; //Return the spine location return UIPageViewControllerSpineLocationMin; } else { NSArray *viewControllers = nil; ContentViewController *currentViewController = [self.pageViewController.viewControllers objectAtIndex:0]; NSUInteger currentIndex = [self.modelArray indexOfObject:[(ContentViewController *)currentViewController textContents]]; if(currentIndex == 0 || currentIndex %2 == 0) { UIViewController *nextViewController = [self pageViewController:self.pageViewController viewControllerAfterViewController:currentViewController]; viewControllers = [NSArray arrayWithObjects:currentViewController, nextViewController, nil]; } else { UIViewController *previousViewController = [self pageViewController:self.pageViewController viewControllerBeforeViewController:currentViewController]; viewControllers = [NSArray arrayWithObjects:previousViewController, currentViewController, nil]; } //Now, set the viewControllers property of UIPageViewController [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL]; return UIPageViewControllerSpineLocationMid; } } - (void)viewDidLoad { [super viewDidLoad]; appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate]; //Instantiate the model array self.modelArray = [[NSMutableArray alloc] init]; self.vcs = [[NSMutableArray alloc]init]; for (int index = 1; index <= 2 ; index++) { [self.modelArray addObject:[NSString stringWithFormat:@"Page %d",index]]; } //Step 1 //Instantiate the UIPageViewController. self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil]; //Step 2: //Assign the delegate and datasource as self. self.pageViewController.delegate = self; self.pageViewController.dataSource = self; //Step 3: //Set the initial view controllers. appDelegate.contentViewController.textContents = [self.modelArray objectAtIndex:0]; NSArray *viewControllers = [NSArray arrayWithObjects:appDelegate.firstViewController,appDelegate.contentViewController,nil]; [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; //Step 4: //ViewController containment steps //Add the pageViewController as the childViewController [self addChildViewController:self.pageViewController]; //Add the view of the pageViewController to the current view [self.view addSubview:self.pageViewController.view]; //Call didMoveToParentViewController: of the childViewController, the UIPageViewController instance in our case. [self.pageViewController didMoveToParentViewController:self]; //Step 5: // set the pageViewController's frame as an inset rect. CGRect pageViewRect = self.view.bounds; pageViewRect = CGRectInset(pageViewRect, 40.0, 40.0); self.pageViewController.view.frame = pageViewRect; //Step 6: //Assign the gestureRecognizers property of our pageViewController to our view's gestureRecognizers property. self.view.gestureRecognizers = self.pageViewController.gestureRecognizers; }
From the Library, add a button to the first View Controller and name the button, for example: Show Second View . Select the button, press and hold the Control key on the keyboard and drag from the button to the second View Controller.
SwiftUI works seamlessly with the existing UI frameworks on all Apple platforms. For example, you can place UIKit views and view controllers inside SwiftUI views, and vice versa.
The problem is you passing an array containing two view controllers to the page view controller while it expects one at a time, change your array to be like this :
NSArray *viewControllers = @[appDelegate.firstViewController];
You will pass one of the views but viewControllerAfterViewController
and viewControllerBeforeViewController
will handle the rest.
Ah..Finally got solution for this same issue.., it may helps you..
When we set the spine location to UIPageViewControllerSpineLocationMid
, the doubleSided
property of the pageViewController is automatically set to YES. This means that the content on page front will not partially show through back. But when this property is set to NO, the content on page front will partially show through back, giving the page a translucent kind of effect. So, in the portrait orientation, we have to set the value to NO, otherwise it would result in an exception.
So in your UIPageviewcontroller
delegate method, in else part add this doubleSided
property as YES when you return spineLocation as UIPageViewControllerSpineLocationMid
self.pageViewController.doubleSided = YES; return UIPageViewControllerSpineLocationMid;
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