Irohabook
0
1808

SwiftのUIPageViewControllerの基本的な使い方(ストーリーボードなし)

ページをめくる画面はUIPageViewControllerで設計する。この記事ではストーリーボードを使わないやり方を解説する。

基本的なコード

YourViewControllerというUIPageViewControllerを設計するとき、基本的なコードは次のようになる。

class YourViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {

    var pages: [UIViewController] = []

    override init(transitionStyle style: UIPageViewControllerTransitionStyle, navigationOrientation: UIPageViewControllerNavigationOrientation, options: [String : Any]? = nil) {
        let t = UIPageViewControllerTransitionStyle.scroll
        let n = UIPageViewControllerNavigationOrientation.horizontal
        super.init(transitionStyle: t, navigationOrientation: n, options: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.dataSource = self
        self.delegate = self
        let v = self.pages[0]
        self.setViewControllers([v], direction: .forward, animated: true, completion: nil)
    }

    func presentationCount(for pageViewController: UIPageViewController) -> Int {
        return pages.count
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard let i = pages.index(of: viewController) else {
            return nil
        }
        let p = i - 1
        if p < 0 {
            return nil
        }
        if pages.count <= p {
            return nil
        }
        return pages[p]
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard let i = pages.index(of: viewController) else {
            return nil
        }
        let n = i + 1
        if n == pages.count {
            return nil
        }
        if pages.count <= n {
            return nil
        }
        return pages[n]
    }
}

クラスの継承

UIPageViewControllerを使うときは

  • UIPageViewController
  • UIPageViewControllerDataSource
  • UIPageViewControllerDelegate

の3つを継承する。

pagesを用意する

フィールド(クラスの変数)にページのデータを用意する。今回はpagesとした。pagesはUIViewControllerの配列である。

presentationCountと2つのpageViewControllerを用意する

presentationCountは上のコードにあるようにpagesの数を返すだけの関数。

UIPageViewControllerというクラス、そしてページ画面のポイントは2つのpageViewControllerにある。UIPageViewControllerはページを戻るときと、ページを進めるときの動作を表す。

  • ページを戻す(viewControllerBefore)
  • ページを進める(viewControllerAfter)

どちらも最初に

let i = pages.index(of: viewController)

で現在のページ番号を取得する。ページを戻すときはこの値に1引いた数、ページを進めるときはこの値に1足した数が「遷移後のページ番号」になる。

このページ番号は、0未満であっても、総ページ数を超えてもいけない。範囲を逸脱したときはnilを返す。

viewDidLoadではsetViewControllersを用意する

最初の画面さえ用意すれば「ページを戻す関数」と「ページを進める関数」に任せておけばいい。後は「最初のページを用意するもの」が必要だ。それがsetViewControllersになる。

setViewControllersには最初のページを入れる。

let v = self.pages[0]
self.setViewControllers([v], direction: .forward, animated: true, completion: nil)

不思議なことに最初のページ(UIViewController)は配列の形にしてsetViewControllersに入れる。

ページめくりのアニメーションはinitで決める

initで親のinitを呼び出す。その引数(transitionStyleとnavigationOrientation)でページめくりの形が決まる。

super.init(transitionStyle: t, navigationOrientation: n, options: nil)

transitionStyleには「スクロール型」と「ページをめくる型」がある。デフォルトは後者だが、後者はアニメーションが独特であり、本を読むアプリでない限りは前者を採用したほうが無難になる。

次の記事

UIPageViewController