I have a PageContainerViewController ( a regular view controller with nothing in it ) that I Show Detail present from a previous view controller, which is supposed to embed a UIPageViewController in itself. The UIPageViewController is supposed to show, right now, two View Controllers, but it doesn't. The PageContainerViewController shows up as a blank white screen, and the UIPageViewController seems to be nowhere (I changed the background color to a bright green and still all I see is white).
Here's my code in PageContainerViewController (which has the UIPageViewControllerDataSource):
var pageViewController: UIPageViewController?
lazy var orderedViewControllers: [UIViewController] = {
return [self.newVc(viewController: "vc1"),
self.newVc(viewController: "vc2")]
}()
var currentlyShowingIndex = 0
func newVc(viewController: String) -> UIViewController {
return storyboard!.instantiateViewController(withIdentifier: viewController)
}
override func viewDidLoad() {
super.viewDidLoad()
pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)ntroller
pageViewController?.dataSource = self
let arr: [UIViewController] = [orderedViewControllers.first!]
pageViewController?.setViewControllers(arr, direction: .forward, animated: false, completion: nil)
pageViewController?.view.frame = self.view.bounds
self.addChildViewController(self.pageViewController!)
self.view.addSubview(self.pageViewController!.view)
pageViewController?.didMove(toParentViewController: self)
pageViewController?.view.backgroundColor = UIColor.green
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else {
return nil
}
let previousIndex = viewControllerIndex - 1
guard previousIndex >= 0 else {
return nil
}
guard orderedViewControllers.count > previousIndex else {
return nil
}
currentlyShowingIndex -= 1
return orderedViewControllers[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else {
return nil
}
let nextIndex = viewControllerIndex + 1
let orderedViewControllersCount = orderedViewControllers.count
guard orderedViewControllersCount != nextIndex else {
return nil
}
guard orderedViewControllersCount > nextIndex else {
return nil
}
currentlyShowingIndex += 1
return orderedViewControllers[nextIndex]
}
func viewController(at index: Int) -> UIViewController {
return orderedViewControllers[index]
}
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
return currentlyShowingIndex
}
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return orderedViewControllers.count
}
So, at least in your original set up, yopu should also conform to delegate:
class PageContainerViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegateYou say:
I want to create the UIPageViewController with code, and add it to the PageContainerViewController.
You can add a view, but how do you add the viewController ?
Here is the full set up I tested:
A PageViewController, with horizontral navigation and Page Curl defined in IB
3 UIViewControllers, with storyboard ID as Page1, Page2, Page3
On each, just a label with the Page x content and a UIImageView with colored background
In PageViewController, I define a pageControl programmatically
Here is the code for the PageViewController.
import UIKit
class PageViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {
let lightGray = UIColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 1.0)
var pageControl = UIPageControl()
func newVc(viewControllerID: String) -> UIViewController {
return storyboard!.instantiateViewController(withIdentifier: viewControllerID)
}
lazy var orderedViewControllers: [UIViewController] = {
return [self.newVc(viewControllerID: "Page1"),
self.newVc(viewControllerID: "Page2"),
self.newVc(viewControllerID: "Page3")]
}()
var currentlyShowingIndex = 0
override func viewDidLoad() {
super.viewDidLoad()
let childControllers: [UIViewController] = [orderedViewControllers.first!]
self.setViewControllers(childControllers, direction: .forward, animated: false, completion: nil)
self.view.frame = self.view.bounds
self.dataSource = self
self.delegate = self
configurePageControl()
}
func configurePageControl() {
pageControl = UIPageControl(frame: CGRect(x: 0,y: UIScreen.main.bounds.maxY - 50,width: UIScreen.main.bounds.width,height: 50))
self.pageControl.numberOfPages = orderedViewControllers.count
self.pageControl.currentPage = 0
self.pageControl.tintColor = UIColor.black
self.pageControl.pageIndicatorTintColor = lightGray // UIColor.gray
self.pageControl.currentPageIndicatorTintColor = UIColor.green
// self.pageControl.defersCurrentPageDisplay = false // This has no effect
self.view.addSubview(pageControl)
}
// MARK: Delegate functions
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
let pageContentViewController = pageViewController.viewControllers![0]
self.pageControl.currentPage = orderedViewControllers.index(of: pageContentViewController)!
switch self.pageControl.currentPage {
case 0: self.pageControl.currentPageIndicatorTintColor = .green
case 1: self.pageControl.currentPageIndicatorTintColor = .orange
case 2: self.pageControl.currentPageIndicatorTintColor = .red
default: self.pageControl.currentPageIndicatorTintColor = lightGray // .gray
}
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else {
return nil
}
let previousIndex = viewControllerIndex - 1
guard previousIndex >= 0 else {
return nil
}
guard orderedViewControllers.count > previousIndex else {
return nil
}
currentlyShowingIndex -= 1
return orderedViewControllers[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else {
return nil
}
let nextIndex = viewControllerIndex + 1
let orderedViewControllersCount = orderedViewControllers.count
guard orderedViewControllersCount != nextIndex else {
return nil
}
guard orderedViewControllersCount > nextIndex else {
return nil
}
currentlyShowingIndex += 1
return orderedViewControllers[nextIndex]
}
func viewController(at index: Int) -> UIViewController {
return orderedViewControllers[index]
}
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
return currentlyShowingIndex
}
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return orderedViewControllers.count
}
}