読者です 読者をやめる 読者になる 読者になる

UIPageViewControllerを使ってみる

UIPageViewControllerを使って前後にページングするViewController群を実装してみましょう。

実装するもの

こんな感じ↓

UIPageViewControllerの構造

こんな感じ↓

  • ↑上、子供
  • ③ ViewController(1…n)
  • ② PageViewController
  • ① RootViewController
  • ↓下、親

UITableViewControllerのように、UIPageViewControllerを実装すればそのビューがページングをすると勘違いしていたのですが、UIPageViewControllerが提供するのはページング要素だけなので、親が必要になります。スクロール対象のViewControllerもこの親が生成しています。PageViewControllerは骨格を提供しているだけという感じです。

コードで

RootViewController

すべての親としてRootViewControllerを配置します。ここで、

  • 最初に表示されるViewControllerを指定
  • PageViewControllerを作成して自分の子ViewControllerとして保持

します。さらにこのViewControllerで UIPageViewControllerDataSource プロトコルを実装していきます。ここで、

  • PageViewが「前」または「後」にスクロールしたときに何を表示するのかを指定

します。

import UIKit

class RootViewController: UIViewController, UIPageViewControllerDataSource {
    override func viewDidLoad() {
        super.viewDidLoad()

        // 最初に表示するViewControllerです
        let contentStoryboard = UIStoryboard(name: "ViewController", bundle: nil)
        let contentViewController = contentStoryboard.instantiateInitialViewController() as! ViewController

        // PageViewです
        let pageStoryboard = UIStoryboard(name: "PageViewController", bundle: nil)
        let pageViewController = pageStoryboard.instantiateInitialViewController() as! PageViewController

        // PageViewに最初に宣言したViewControllerを配置します。
        // [contentViewController] という感じで1要素の配列として渡していきます
        pageViewController.setViewControllers([contentViewController], direction: .forward, animated: true, completion: nil)
        addChildViewController(pageViewController)

        // このクラスでPageViewControllerの情報受け渡し役を担当します
        pageViewController.dataSource = self

        // RootViewControllerのビューにPageViewControllerのビューを載せます
        view.addSubview(pageViewController.view)
        pageViewController.didMove(toParentViewController: self)
    }

    // 「後」にページングしたときに見せたいViewControllerのセッティングです
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        let storyboard = UIStoryboard(name: "ViewController", bundle: nil)
        let viewController = storyboard.instantiateInitialViewController() as! ViewController
        return viewController
    }

    // 「前」にページングしたときに見せたいViewControllerのセッティングです
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        let storyboard = UIStoryboard(name: "ViewController", bundle: nil)
        let viewController = storyboard.instantiateInitialViewController() as! ViewController
        return viewController
    }
}

PageViewController

StoryboardでUIPageViewControllerを置いてあげればOKです。

クラス宣言以降特に何もしていません。

import UIKit

class PageViewController: UIPageViewController {

}

ViewController

StoryboardでUIViewControllerを置いてあげればOKです。

サンプルでは中央に「わーい」と書いたUILabelを配置しました。

import UIKit

class ViewController: UIViewController {

}

サンプルコード

ビルドしてお手元で確かめる際にお役立てください。

https://github.com/keisei1092/PageViewControllerPractice/