複数のstoryboardを使って、コードで画面遷移を実装する


iPhone5、iPhone6/6Plusが発売になってからというもの、iOSアプリもデバイスの大きさに応じたデザインを考える必要がでてきました。それに応じて、storyboardではconstrains（日本語ではよく制約と呼ばれています）というルールを使ってレイアウトをある程度自動で調整してくれるautolayout機能が用意されています。

storyboardは画面遷移なども定義できる優れものですが、動作の都合上特定のビューコントローラに接続される数が多過ぎると事実上storyboardでの実装が難しかったり、オブジェクトやconstrainsが増えてくると、アプリ内の全ページを１つのstoryboardファイルで処理するのは大変だなあ…という事態に陥りました。条件によって遷移先が違う場合等storyboardだけだと面倒なケースもあると思います。

（あと、storyboardでの作業めちゃくちゃ重いのでできればファイル内をシンプルにしたい…）
アプリ内の全画面を扱うstoryboardをGit等で管理していると、編集時にconflictも発生するかもしれません。


ということで、この記事では、
・アプリの各画面毎にstoryboardファイルを用意してデザインを作る
・コードでこれらの遷移を実装する
ということを書こうと思います。

##プロジェクトの設定と最初の画面
Xcode6では新しくプロジェクト(SingleViewApplicationの場合)を作成すると、「Main.storyboard」が自動で作成され、プロジェクト設定の「General -> Deployment info -> Main Interface」の項目が「Main」と設定されています。今回はNavigationControllerによる画面遷移をコードからやりたいので、この項目は削除します。

続いて、AppDelegate.swiftに次のように追記します。

```swift:AppDelegate.swift
import UIKit

@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var navigationController: UINavigationController?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        
        var storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
        var mainViewController: UIViewController = storyboard.instantiateInitialViewController() as UIViewController

        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        self.navigationController = UINavigationController(rootViewController: mainViewController)
        
        self.window?.rootViewController = navigationController
        self.window?.makeKeyAndVisible()
        
        return true
    }

	// 省略
}
```

ここで実行すると、Main.storyboardでデザインした画面が表示されると思います。

```
var storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
var mainViewController: UIViewController = storyboard.instantiateInitialViewController() as UIViewController
```
の部分で、「Main」という名前のファイルからstoryboardを取得して、instantiateInitialViewController()メソッドでstoryboardファイル内で「is initial view controller」に設定されてあるViewControllerを取得しています。

「is initial view controller」は自動生成されたMain.storyboardでは初期値がONになっているのでここでは特に考えなくても大丈夫だと思います。次項でもう少し詳しく書きます。

##遷移先の画面を作成する
文頭で述べたように、「File -> New -> File」から新しくstoryboardと、任意のUIViewControllerのサブクラスを作成します。ここでは、「SecondViewController.swift」と「SecondViewControlelr.storyboard」を作ったとして続けます。

はじめに、SecondViewController.storyboardを開いて、ViewControllerを配置し、設置したViewControllerを選択した状態で、インスペクタの「Show the Identity inspector」タブの「Custom Class」の項目にSecondViewControllerを設定します。

次に、「Show the Atributes inspector」タブの「View Controller」にある「is Initial View Controller」のチェックを入れます。上で説明したinstantiateInitialViewController()メソッドは、ここのチェックが入っているViewControllerを取得するので、付け忘れると動作しないです。忘れがちなので要注意です。

![スクリーンショット 2014-10-11 17.58.34.png](https://qiita-image-store.s3.amazonaws.com/0/48393/077efc7d-f07a-95a2-f61a-f517bc200a1a.png "スクリーンショット 2014-10-11 17.58.34.png")


##画面遷移を実装する
最後に、コードで画面遷移を実装します。AppDelegateでNavigationControllerを設定したので、MainからSecondViewControllerを呼び出すときは、AppDelegateで書いたときと同じように、次のようにします。

```swift:Main.swift
var storyboard: UIStoryboard = UIStoryboard(name: "SecondViewController", bundle: NSBundle.mainBundle())
var secondViewController: SecondViewController = storyboard.instantiateInitialViewController() as SecondViewController

self.navigationController?.pushViewController(secondViewController, animated: true)
```

前の画面に戻るときは、今までと特に変わりなく、

```swift:SecondViewController.swift
self.navigationController?.popViewControllerAnimated(true)
```

とできます。