【決定版】UIPageViewControllerの使い方（Swift）



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




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

#完成図
![aaa.gif](https://qiita-image-store.s3.amazonaws.com/0/96201/e5fcaaf7-f454-63ea-5690-8dad897d0b82.gif "aaa.gif")


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


##ViewControllerを準備
####1.画像を参考に３つ適当なViewControllerを準備してください。それぞれ区別がつけば、レイアウトなどは適当で構いません。
![スクリーンショット 2016-04-10 4.41.28 AM.png](https://qiita-image-store.s3.amazonaws.com/0/96201/0e9a6fc2-a7ef-b89a-4c0c-f04f21a7c83f.png "スクリーンショット 2016-04-10 4.41.28 AM.png")

####2.それに対応したファイルも３つ作って、それぞれのViewControllerに指定してください。
####3.また、StoryBoardIDも忘れずに設定するようにしましょう。
![スクリーンショット 2016-04-10 4.46.22 AM.png](https://qiita-image-store.s3.amazonaws.com/0/96201/af5d4c22-3ece-1d3f-a7b7-3266134f91ca.png "スクリーンショット 2016-04-10 4.46.22 AM.png")


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

##UIPageViewControllerを準備
####1.オブジェクトライブラリからドラック＆ドロップでUIPageViewControllerを追加
![スクリーンショット 2016-04-10 4.48.52 AM.png](https://qiita-image-store.s3.amazonaws.com/0/96201/fb6f9f9c-b7da-6c70-d893-f4ebfed48d31.png "スクリーンショット 2016-04-10 4.48.52 AM.png")

####2.画像を参考にUIPageViewControllerの設定を変更
![スクリーンショット_2016-04-10_4_51_19_AM.png](https://qiita-image-store.s3.amazonaws.com/0/96201/cc37c4c2-626f-0693-c34b-397066a836ed.png "スクリーンショット_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()メソッドの第一引数は配列になっていますが、基本的に１つのViewControllerを入れるだけで構いません。iBooksのようなアプリを作る場合に複数のViewControllerを入れます。（この点については今回は詳しく触れませんが、気になる方は調べてみてください。）

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

####3.dataSource
次の残りの２つの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.最後に残りの２つの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
        }
    }
}
```