Storyboardを使ってContainerView+PageViewのサンプルを作ってみた

#概要
横スクロールするメニュー＋メニューに連動してメインビューが切り替わる、
SmartNews等のアプリで見られるような、簡易なサンプルを作ってみました。
ポイントはこんな感じです。
・可能な限りStoryboadを使う（+Swift）
・横スクロールするメニュー⇒ScrollView+StackView
・メインビュー⇒ContainerView+PageView

このあたりの記事を参考にさせていただきました。
http://crossbridge-lab.hatenablog.com/entry/2015/12/26/210600
http://qiita.com/nofrmm/items/5cc122876b6c3af7a21e

#ソース
ざっくりとした内容しか記載していないのでソース見たい方はこちらからどうぞ
https://github.com/koji-nishida/scrollmenu-container-pageview

#完成イメージ

![サンプル.gif](https://qiita-image-store.s3.amazonaws.com/0/38124/2ce40207-b1c6-e23a-3753-516c02091716.gif)

#全体図


![スクリーンショット 2016-08-19 14.59.16.png](https://qiita-image-store.s3.amazonaws.com/0/38124/70ae9e1a-259b-8c95-e2a6-978f5c194a0c.png)

![スクリーンショット 2016-08-19 15.01.04.png](https://qiita-image-store.s3.amazonaws.com/0/38124/ed8bdfa7-dd99-a78d-71cd-7f82761278d2.png)


#メニュー部の作成
ScrollView、StackView、Buttonを配置
Constraintsは下図のような感じ（Buttonは特に制約なし）
これで端末幅に合わせて横スクロールするメニューが完成
![スクリーンショット 2016-08-20 10.32.10.png](https://qiita-image-store.s3.amazonaws.com/0/38124/7a8055a0-e251-f5c8-9566-ee48a0d41af2.png)

![スクリーンショット 2016-08-20 10.30.10.png](https://qiita-image-store.s3.amazonaws.com/0/38124/98fe1e50-f30d-039e-74cf-3aa82040a876.png)
ScrollViewのConstraints

![スクリーンショット 2016-08-20 10.31.53.png](https://qiita-image-store.s3.amazonaws.com/0/38124/a9a1314b-1ea3-ad2a-bc7b-36eccd8f7d51.png)
StackViewのConstraints


#メインビュー部の作成
図のようにメニューの下にContainerViewを配置。
配置時点ではUIViewControllerがembedされているので、
UIViewControllerを消して、UIPaveViewControllerを配置しなおします。
ここでUIPaveViewControllerのCustom ClassにPageViewController.swiftを指定しておく。
![スクリーンショット 2016-08-20 10.40.06.png](https://qiita-image-store.s3.amazonaws.com/0/38124/63157e2d-4867-2696-ff45-c3d7a4ffbbd3.png)
![スクリーンショット 2016-08-20 10.39.41.png](https://qiita-image-store.s3.amazonaws.com/0/38124/9bd18ad0-9615-0982-bbca-c91d55fef201.png)
ContainerViewのConstraints

#実装部（PageViewにViewControllerをセット）
```HomeViewController.swift
    var pageViewController: PageViewController!
    var menuViewControllers: Array<UIViewController> = []
    var selected: Int!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // PageViewControllerを取得する
        for vc in childViewControllers {
            if vc is PageViewController {
                pageViewController = vc as! PageViewController
            }
            
        }
        
        // PageViewにセットするViewControllerを生成して配列に入れる
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let firstViewController = storyboard.instantiateViewControllerWithIdentifier("FirstViewController") as! FirstViewController
        let secondViewController = storyboard.instantiateViewControllerWithIdentifier("SecondViewController") as! SecondViewController
        let thirdViewController = storyboard.instantiateViewControllerWithIdentifier("ThirdViewController") as! ThirdViewController
        let fourthViewController = storyboard.instantiateViewControllerWithIdentifier("FourthViewController") as! FourthViewController
        menuViewControllers.append(firstViewController)
        menuViewControllers.append(secondViewController)
        menuViewControllers.append(thirdViewController)
        menuViewControllers.append(fourthViewController)
        
        // 初期表示をメニュー2(SecondViewController)にする
        pageViewController.setViewControllers([menuViewControllers[1]], direction: .Forward, animated: false, completion: nil)
        selected = 1
    }


puts 'The best way to log and share programmers knowledge.'
```

ポイント
・childViewControllersからPageViewControllerを探す
　もっといい方法があれば誰か教えて下さい
・各ViewControllerをStoryboardから生成して配列で保持しておく
・初期表示するViewControllerをセット

#実装部（メニュー切り替え部）
```HomeViewController.swift
@IBAction func actionMenu1(sender: AnyObject) {
        self.btnMenu1.enabled = false
        self.btnMenu2.enabled = true
        self.btnMenu3.enabled = true
        self.btnMenu4.enabled = true
        
        // 一番左までスクロール
        scrollViewMenu.setContentOffset(CGPointMake(0, 0), animated: true);
        
        // 表示切り替え
        pageViewController!.setViewControllers([menuViewControllers[0]], direction: .Reverse, animated: true, completion: nil)
        
        selected = 0
        
    }
    
    @IBAction func actionMenu2(sender: AnyObject) {
        self.btnMenu1.enabled = true
        self.btnMenu2.enabled = false
        self.btnMenu3.enabled = true
        self.btnMenu4.enabled = true
        
        // 一番左までスクロール
        scrollViewMenu.setContentOffset(CGPointMake(0, 0), animated: true);
        
        // 表示切り替え（前回選択していたメニューの位置に応じてアニメーションの向きを設定）
        if (selected < 1) {
            pageViewController!.setViewControllers([menuViewControllers[1]], direction: .Forward, animated: true, completion: nil)
        } else {
            pageViewController!.setViewControllers([menuViewControllers[1]], direction: .Reverse, animated: true, completion: nil)
        }
        
        selected = 1
        
    }
    
    @IBAction func actionMenu3(sender: AnyObject) {
        self.btnMenu1.enabled = true
        self.btnMenu2.enabled = true
        self.btnMenu3.enabled = false
        self.btnMenu4.enabled = true

        // 一番右までスクロール
        let scrollWidth = scrollViewMenu.contentSize.width - scrollViewMenu.frame.size.width
        scrollViewMenu.setContentOffset(CGPointMake(scrollWidth, 0), animated: true);
        
        // 表示切り替え（前回選択していたメニューの位置に応じてアニメーションの向きを設定）
        if (selected < 2) {
            pageViewController!.setViewControllers([menuViewControllers[2]], direction: .Forward, animated: true, completion: nil)
        } else {
            pageViewController!.setViewControllers([menuViewControllers[2]], direction: .Reverse, animated: true, completion: nil)
        }
        
        selected = 2
        
    }
    
    @IBAction func actionMenu4(sender: AnyObject) {
        self.btnMenu1.enabled = true
        self.btnMenu2.enabled = true
        self.btnMenu3.enabled = true
        self.btnMenu4.enabled = false

        // 一番右までスクロール
        let scrollWidth = scrollViewMenu.contentSize.width - scrollViewMenu.frame.size.width
        scrollViewMenu.setContentOffset(CGPointMake(scrollWidth, 0), animated: true);
 
        // 表示切り替え
        pageViewController!.setViewControllers([menuViewControllers[3]], direction: .Forward, animated: true, completion: nil)
        
        selected = 3
        
    }
```
ポイント
・特になし笑

#最後に
Storyboardもずいぶん便利になったなーというのが一番の感想ですかね。
一昔前ではコードをがりがり書かないとできなかったようなことが、
Storyboardでこんなに簡単に作れるようになったなーという印象です。

今回は、メニューボタンのアクションによる画面切り替えしか対応していないので、
メインビュー部分をスクロールさせることでも画面がスライドするようにしないとですね。
ContainerViewのジェスチャーをとって、画面を切り替えるという感じでしょうか。


以上