LoginSignup
223
198

More than 5 years have passed since last update.

【決定版】UIPageViewControllerの使い方(Swift)

Last updated at Posted at 2016-04-10

UIPageViewControllerとは

(※僕自身の個人的な解釈、予想です。)
UIPageViewControllerとは画面遷移に使われる一種のコントローラーです。NavigationControllerやTabBarControllerのようなものです。
実際のアプリケーションでは、SmartNews、SnapChat、TinderなどのUIや、様々なアプリケーションの初回起動時の使用方法説明画面などに使われています。
UIScrollViewでもにたような機能は実装できるのですが、別々なViewControllerをつなげることができるUIPageViewControllerの方がすっきりとしたコードが書けるようになるため、優れていると思います。

日本語の文献が少なく実装に苦労したので、ここにまとめたいと思います。一度覚えてしまえば、簡単に実装ができ、また便利な機能なので頑張っていきましょう!

完成図

aaa.gif

実装手順

1.繋げたいViewControllerを用意
2.UIPageViewControllerを作成
3.コードを記述

ViewControllerを準備

1.画像を参考に3つ適当なViewControllerを準備してください。それぞれ区別がつけば、レイアウトなどは適当で構いません。

スクリーンショット 2016-04-10 4.41.28 AM.png

2.それに対応したファイルも3つ作って、それぞれのViewControllerに指定してください。

3.また、StoryBoardIDも忘れずに設定するようにしましょう。

スクリーンショット 2016-04-10 4.46.22 AM.png

以上の3つのViewControllerをUIPageViewControllerを使い、スワイプで画面遷移できるようにしていきたいと思います。

UIPageViewControllerを準備

1.オブジェクトライブラリからドラック&ドロップでUIPageViewControllerを追加

スクリーンショット 2016-04-10 4.48.52 AM.png

2.画像を参考にUIPageViewControllerの設定を変更

スクリーンショット_2016-04-10_4_51_19_AM.png

以上がが、StoryBoardでの作業になります。
ここまでをまとめると、繋げたいViewControllerとPageViewControllerを用意し、StoryboardID、TransitionStyle、InitialViewControllerなどの設定をしただけです。

次からはソースコードでの作業になります。

UIPageViewControllerを編集しよう

1.まずUIPageViewControllerクラスを継承したファイルを作成

ファイル名は、「PageViewController」にしてください。
忘れずに、StoryboardのUIPageViewControllerとの関連付けもしましょう。

2.最初の画面を設定

ファイルを以下のように編集しましょう

PageViewController.swift
import UIKit

class PageViewController: UIPageViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.setViewControllers([getFirst()], direction: .Forward, animated: true, completion: nil)
    }

    func getFirst() -> FirstViewController {
        return storyboard!.instantiateViewControllerWithIdentifier("FirstViewController") as! FirstViewController
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

ここではStoryboardからFirstViewControllerを読み込み、それをsetViewControllers()メソッドを使い、初期画面に設定しています。また、setViewControllers()メソッドの第一引数は配列になっていますが、基本的に1つのViewControllerを入れるだけで構いません。iBooksのようなアプリを作る場合に複数のViewControllerを入れます。(この点については今回は詳しく触れませんが、気になる方は調べてみてください。)

このタイミングで一度ビルドして、正常に起動するか確認してください。

3.dataSource

次の残りの2つのViewControllerをつなげていきたいと思います。
次のようにPageViewControllerファイルを編集してください。

PageViewController.swift

import UIKit

class PageViewController: UIPageViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.setViewControllers([getFirst()], direction: .Forward, animated: true, completion: nil)
        self.dataSource = self //追加
    }
     省略
}

//以下追加
extension PageViewController : UIPageViewControllerDataSource {

    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        return nil
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        return nil
    }   
}

複数のViewControllerはdataSourceプロトコルを使い実装していきます。

4.最後に残りの2つのViewControllerを繋げていきます。

クラス内の適当な箇所に以下のように追記してください。

PageViewController.swift
func getSecond() -> SecondViewController {
        return storyboard!.instantiateViewControllerWithIdentifier("SecondViewController") as! SecondViewController
    }

    func getThird() -> ThirdViewController {
        return storyboard!.instantiateViewControllerWithIdentifier("ThirdViewController") as! ThirdViewController
    }

そして、先ほどのデリゲードメソッドを次のように編集しましょう。

(注)pageViewController(___After_)メソッドです

PageViewController.swift
    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        if viewController.isKindOfClass(FirstViewController) {
            // 1 -> 2
            return getSecond()
        } else if viewController.isKindOfClass(SecondViewController) {
            // 2 -> 3
            return getThird()
        } else {
            // 3 -> end of the road
            return nil
        }
    }

もし現在の画面が
・FirstVCだった場合、SecondVCを
・SecondVCだった場合、ThirdVCを
・FirstVCだった場合、次(After)のページはないのでnilを
返しています。

逆もしかりです。
ページを戻す場合は、pageViewController(___before_)メソッドに次のように記述してあげることで実装できます。

PageViewController.swift
    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        if viewController.isKindOfClass(ThirdViewController) {
            // 3 -> 2
            return getSecond()
        } else if viewController.isKindOfClass(SecondViewController) {
            // 2 -> 1
            return getFirst()
        } else {
            // 1 -> end of the road
            return nil
        }
    }

完成コード

PageViewController.swift
import UIKit

class PageViewController: UIPageViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.setViewControllers([getFirst()], direction: .Forward, animated: true, completion: nil)
        self.dataSource = self
    }

    func getFirst() -> FirstViewController {
        return storyboard!.instantiateViewControllerWithIdentifier("FirstViewController") as! FirstViewController
    }

    func getSecond() -> SecondViewController {
        return storyboard!.instantiateViewControllerWithIdentifier("SecondViewController") as! SecondViewController
    }

    func getThird() -> ThirdViewController {
        return storyboard!.instantiateViewControllerWithIdentifier("ThirdViewController") as! ThirdViewController
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

extension PageViewController : UIPageViewControllerDataSource {

    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        if viewController.isKindOfClass(ThirdViewController) {
            // 3 -> 2
            return getSecond()
        } else if viewController.isKindOfClass(SecondViewController) {
            // 2 -> 1
            return getFirst()
        } else {
            // 1 -> end of the road
            return nil
        }
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        if viewController.isKindOfClass(FirstViewController) {
            // 1 -> 2
            return getSecond()
        } else if viewController.isKindOfClass(SecondViewController) {
            // 2 -> 3
            return getThird()
        } else {
            // 3 -> end of the road
            return nil
        }
    }
}
223
198
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
223
198