Using the Page View Controller

One unique way to display the contents of two or more View Controllers is through a Page View Controller, which lets users swipe left and right. Each swipe displays a different View Controller like swiping through pages in an e-book. To use a page controller, you need to add a Page Controller to a storyboard. Then you can customize this Page Controller by defining the following properties in the Attributes Inspector pane:

  • Navigation. Defines whether the user needs to swipe horizontally or vertically to display the next or previous view.
  • Transition style. Defines whether views curl like pages in a book (page curl) or whether they simply slide in place (scroll).

After customizing the behavior of the Page Controller, the next step is to create multiple View Controllers that are completely separate from the storyboard (not connected to any existing storyboard scenes through segues). To make these View Controllers appear within a Page Controller, each View Controller needs a unique Storyboard ID that you can define within the Identity Inspector pane.

Finally, you need to create separate .swift files and connect them to each View Controller. In addition, you need to create a separate .swift file and connect it to the Page Controller. Altogether, you need two types of .swift files:

  • A single UIPageViewController class file to connect to the Page Controller
  • A UIViewController class file to connect to each View Controller you want to appear inside the Page Controller

Once you’ve added a Page Controller to your storyboard and multiple View Controllers that are not connected to any part of the storyboard through segues, you can then write Swift code to load the multiple View Controllers.

Adding and Customizing a Page Controller

The first step to using a Page Controller is to add one to your storyboard. To see how to place a Page Controller in a storyboard, follow these steps:

  1. Click the Main.storyboard file in the Navigator pane. Xcode displays the single view.
  2. Click the Library icon to open the Object Library window.
  3. Drag and drop a Page Controller from the Object Library window to the storyboard
  4. Click the Page View Controller icon at the top of the Page Controller.
  5. Click the Attributes Inspector icon in the upper right corner of the Xcode window.
  6. Click in the Navigation popup menu and choose Horizontal.
  7. Click in the Transition Style popup menu and choose Page Curl.
  8. Select the "Is Initial View Controller" check box.

Adding View Controllers

A Page Controller displays one or more View Controllers. To make each View Controller appear within a Page Controller, each View Controller needs:

  • A unique Storyboard ID (any arbitrary text)
  • A connection to a .swift UIViewController file

To make it obvious when we’re viewing different View Controllers, we also need to change the background color of each View Controller, but in a real app, each View Controller would display different information such as text, pictures, or user interface designs.

To see how to add View Controllers to a storyboard to use in a Page Controller, follow these steps:

  1. Click View under View Controller Scene in the Document Outline to select it.
  2. Click the Attributes Inspector icon in the upper right corner of the Xcode window.
  3. Click the Background popup menu and choose a color such as yellow.
  4. Click the View Controller in the Document Outline
  5. Click the Identity Inspector icon in the upper right corner of the Xcode window.
  6. Click in the Storyboard ID text field, type page01, and press ENTER.
  7. Choose File > New > File. A dialog appears, displaying different templates.
  8. Choose Cocoa Touch Class under the iOS category and then click the Next button. Another window appears letting you choose a name for your file.
  9. Click in the Class text field and type SecondViewController. (Make sure the Subclass of popup menu displays UIViewController.)
  10. Repeat steps 7–9 except name this .swift file as ThirdViewController. The Navigator pane should now display the ViewController.swift, SecondViewController.swift, and ThirdViewController.swift files.
  11. Click the View of the second View Controller in the Document Outline, or click in the middle of the second View Controller.
  12. Click the Attributes Inspector icon in the upper right corner of the Xcode window.
  13. Click in the Background popup menu and choose a color such as orange.
  14. Click the Library icon to open the Object Library window and drag and drop a View Controller from the Object Library window to the storyboard.
  15. Click the Identity Inspector icon in the upper right corner of the Xcode window.
  16. Click in the Class popup menu and choose ThirdViewController.
  17. Click in the Storyboard ID text field, type page03, and press ENTER.
  18. Click the View of the third View Controller in the Document Outline, or click in the middle of the third View Controller.
  19. Click the Attributes Inspector icon in the upper right corner of the Xcode window.
  20. Click the Background popup menu and choose a color such as cyan.

To make multiple View Controllers appear inside a Page Controller, you must first connect the Page Controller to a .swift UIPageController class file. Then within this UIPageController.swift file, you need to write Swift code to do the following:

  • Define an array to hold all the View Controllers to display inside the Page Controller.
  • Write a viewControllerBefore method to define which View Controller to display when the user swipes to open the previous view.
  • Write a viewControllerAfter method to define which View Controller to display when the user swipes to open the next view.

To see how to write Swift code to make a Page Controller work, follow these steps:

  1. Choose File > New > File. A dialog appears displaying different templates available.
  2. Click Cocoa Touch Class under the iOS category and click the Next button. Another window appears, asking for a class name and subclass type.
  3. Click in the Class text field and type PageViewController.
  4. Click in the Subclass of popup menu and choose UIPageViewController.
  5. Click Page View Controller in the Document Outline
  6. Click the Identity Inspector icon at the top right corner of the Xcode window.
  7. Click in the Class popup menu and choose PageViewController.
  8. Click the PageViewController.swift file in the Navigator pane.
  9. Edit the class PageViewController line as follows:
class PageViewController: UIPageViewController, UIPageViewControllerDataSource {

Under the class PageViewController line, add the following line that declares an array of UIViewControllers:

var controllerArray: [UIViewController]? = nil

Modify the viewDidLoad method as follows:

override func viewDidLoad() { 
    super.viewDidLoad() 
    dataSource = self
    let storyBoard = UIStoryboard(name: "Main", bundle: nil) 
    let firstVC = storyBoard.instantiateViewController(withIdentifier: "page01")
    let secondVC = storyBoard.instantiateViewController(withIdentifier: "page02")
    let thirdVC = storyBoard.instantiateViewController(withIdentifier: "page03")

    controllerArray = [firstVC, secondVC, thirdVC]

    self.setViewControllers([controllerArray![0]], 
        direction: UIPageViewController.NavigationDirection.forward, 
        animated: true, completion: nil)
}

Add the following function to define the View Controller to appear when the user displays the previous View Controller:

func pageViewController(_ pageViewController: UIPageViewController, 
    viewControllerBefore viewController: UIViewController) -> UIViewController? {

    guard let vcIndex = controllerArray!.firstIndex(of: viewController) else {
        return nil
    }

    let preIndex = vcIndex - 1
    guard preIndex >= 0 else {
        return controllerArray!.last // loops back to end
    }
    guard controllerArray!.count > preIndex else { 
        return nil
    }
    return controllerArray![preIndex] 
}

Add the following function to define the View Controller to appear when the user displays the next View Controller:

func pageViewController(_ pageViewController: UIPageViewController, 
    viewControllerAfter viewController: UIViewController) -> UIViewController? {

    guard let vcIndex = controllerArray!.firstIndex(of: viewController) else {
        return nil
    }

    let nextIndex = vcIndex + 1
    guard controllerArray!.count != nextIndex else {
        return controllerArray!.first 
    }
    guard controllerArray!.count > nextIndex else { 
        return nil
    }
    return controllerArray![nextIndex]
}