0
votes

So I have a UIPageViewController where I want to implement the spineLocation to be .mid if the device is in landscape and .min for portrait, therefore showing two controllers in landscape and one in portrait.

In the page view controller delegate I implemented this function:

func pageViewController(_ pageViewController: UIPageViewController, spineLocationFor orientation: UIInterfaceOrientation) -> UIPageViewController.SpineLocation {
    if orientation == .landscapeLeft || orientation == .landscapeRight {
        return .mid
    } else {
        return .min
    }
}

In my UIPageViewController class, to set the view controllers I have this function:

func setControllers() {
    var controllers: [UIViewController] = [controller1]
    if spineLocation == .mid {
        controllers.append(controller2)
    }
    setViewControllers(controllers, direction: .forward, animated: true, completion: nil)
}

My problem is that I am not sure of where to put it, I tried in:

  1. viewDidLoad (before setting pageController delegate)
  2. viewDidLoad (after setting pageController delegate)
  3. viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
  4. didRotate(from fromInterfaceOrientation: UIInterfaceOrientation)
  5. willRotate(to toInterfaceOrientation: UIInterfaceOrientation, duration: TimeInterval)

The view is shown correctly in portrait mode but when I start or turn the device to landscape the app crashes for:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'The number of provided view controllers (1) doesn't match the number required (2) for the requested spine location (UIPageViewControllerSpineLocationMid)'


1

1 Answers

0
votes

I fixed it by: Adding the spineLocation as a parameter for the function setControllers:

func setControllers(forSpineLocation location: SpineLocation) {
var controllers: [UIViewController] = [controller1]
if location == .mid {
    controllers.append(controller2)
}
setViewControllers(controllers, direction: .forward, animated: true, completion: nil)

}

And by implementing it on both viewDidLoad and pageViewController(_ pageViewController: UIPageViewController, spineLocationFor orientation: UIInterfaceOrientation):

override func viewDidLoad() {
    super.viewDidLoad()
    setControllers(withLocation: spineLocation)
}

func pageViewController(_ pageViewController: UIPageViewController, spineLocationFor orientation: UIInterfaceOrientation) -> UIPageViewController.SpineLocation {
    var location = SpineLocation.min
    if orientation == .landscapeLeft || orientation == .landscapeRight {
        location = .mid
    }
    setControllers(withLocation: location)
    return location
}

I don't know is this is the correct or best way to do it but it works.