画面遷移まとめ vol.1(どこがコードでどこがStoryboardか)[NavigationController等]

画面遷移を書く時、どこがコードでどこがStoryboardか
どのコードがどのStoryboardでの操作に対応しているのか
毎回ググってもごっちゃになるのでまとめ中です。

あとで追記します。

### 1つのStoryboardにまとめちゃう場合
####・ シンプルに遷移
1.VC2つ用意->右クリックでつなげる(いわゆる`performSegue`)
->Stroyboardのみ(遷移するボタンなどが決まっている)
->NCを`Embed In`した場合モーダル遷移->**プッシュ遷移**になる
->**NCの影響を受ける**

2.VC2つ用意->遷移したいタイミングでこのコード

```swift
let storyboard = self.storyboard!
let nextView = storyboard.instantiateViewController(withIdentifier: "viewcontroller2")
//withIdentifierにはStoryboardの`Identity->StoryboardID`のやつを設定
self.present(nextView, animated: true, completion: nil)
```
->遷移先の指定はStoryboard, 遷移のタイミングはコード
->NCを`Embed In`した場合**モーダル遷移->**プッシュ遷移にならない
->**NCの影響を受けない**


####・ NCで遷移
1.VC2つ用意->右クリックでつなげる->initialVCにNCを`Embed in`(**ViewController Scene**を選択しながら)
->Stroyboardのみ(遷移するボタンなどが決まっている)

2.VC2つ用意->initialVCにNCを`Embed in`(**ViewController Scene**を選択しながら)
->遷移元の黄色ボタン(Storyboard)から先に右クリックでつなげる(遷移元と遷移先を指定しているだけで遷移のタイミングや遷移に用いるUIはコードで決める)
->遷移したいタイミングでこのコード

```swift
performSegue(withIdentifier: "Test", sender: nil)
```
->遷移先の指定はStoryboard, 遷移のタイミングはコード(遷移に用いるVCが2つ程度の時)

3.VC2つ用意->initialVCにNCを`Embed in`(**ViewController Scene**を選択しながら)
->遷移元の黄色ボタン(Storyboard)から先に右クリックでつなげる(遷移元と遷移先を指定しているだけで遷移のタイミングや遷移に用いるUIはコードで決める)
->遷移したいタイミングでこのコード

```swift
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "Test") as! SecoundViewController
//withIdentifierにはStoryboardの`Identity->StoryboardID`のやつを設定
self.navigationController?.pushViewController(secondViewController, animated: true)
//遷移先のVCのCustom ClassをsecondViewControllerにする
````
->遷移先の指定はStoryboard, 遷移のタイミングはコード(遷移に用いるVCが2つ程度の時)

#### NCの先頭に戻る時
戻りたい時これ書く
->単に`segue`で先頭に繋いだ時と異なり**戻るアニメーションになる**
->戻りの遷移も`segue`で繋ぐと(例えばPushで繋ぐと遷移した数だけbackボタン押さないと)**backボタンが出続けるのでやるべきではない**)
->Modalで繋ぐとNCとしてではなくVCとして遷移元を認識するので注意
->NCとModalで繋ぐとNCとして遷移元を認識しnavigationBarが出るが今度は**モーダル遷移の画面の階層がたまり続けるのでやるべきではない**

```swift
    self.navigationController?.popToRootViewController(animated: true)
```

#### NCをEmbed Inした場合、遷移先VCの制約はどうするか
NCを`Embed In`した場合、performSegueで遷移先とつなぐ->遷移先にもnavBarがつく(そいつもNCの配下になるから)
->コードで繋ぐ場合、遷移先にもnavBarがつかないので(そいつもNCの配下にならないから)navBarや他のUIを`Storyboard`で書くのかコードで書くのか？？
->実際には現れるnavBarが`Storyboard`には出てこないので困った
->**あとで追記**

### 1VC = 1Storyboardにする(StoryboardをVCごとに分割)する場合
`First.storyboard`の`FirstHomeVC`(NCをEmbed In済)->`Second.storyboard`の`SecondHomeVC`に**プッシュ遷移**
#### NCで遷移
VC2つ用意->initialVCにNCを`Embed in`(**ViewController Scene**を選択しながら)
->遷移元の黄色ボタンで`@IBAction toSecondHome`を定義->遷移したいタイミングでこのコード
**※Storyboardが分かれる場合はStoryboardとVCを両方指定する**

```swift
  @IBAction func toSecondHome(_ sender: Any) {
        let storyboard: UIStoryboard = UIStoryboard(name: "Second", bundle: nil)
//遷移先のStoryboardを設定
        let SecondVC = storyboard.instantiateViewController(withIdentifier: "Second") as! SecondHomeVC
//遷移先のViewControllerを設定
        self.navigationController?.pushViewController(SecondVC, animated: true)
    }
}
```

#### モーダル遷移
`First.storyboard`の`FirstHomeVC`(NCをEmbed In済)->`Second.storyboard`の`SecondHomeVC`に**モーダル遷移**

```swift
let storyboard: UIStoryboard = UIStoryboard(name: "Second", bundle: nil)
//遷移先のStoryboardを設定
let SecondVC = storyboard.instantiateViewController(withIdentifier: "Second") as! SecondHomeVC
//遷移先のViewControllerを設定
self.present(SecondVC, animated: true, completion: nil)//遷移する
```

`First.storyboard`の`FirstHomeVC`(NCをEmbed In済)->`Second.storyboard`の`SecondHomeVC`(NCをEmbed In済)に**モーダル遷移**
NC埋め込んでても↑のままでもできますが`SecondHomeVC`=普通のVCと認識して遷移します->**navigationBarは出ません**

```swift
let storyboard: UIStoryboard = UIStoryboard(name: "Second", bundle: nil)
//遷移先のStoryboardを設定
let navigationController = storyboard.instantiateViewController(withIdentifier: "NC") as! UINavigationController
//遷移先のNavigationControllerを設定 //こっちだとnavigationBar出る
self.present(navigationController, animated: true, completion: nil)
//遷移する
```

#### モーダル遷移で戻る
[先ほど](https://qiita.com/drafts/a0be9cd3351568ad2889/edit#nc%E3%81%AE%E5%85%88%E9%A0%AD%E3%81%AB%E6%88%BB%E3%82%8B%E6%99%82)書いたのと同じ理由で、戻るときはsegueで行き先指定するとかではなく
**戻る用のコードを書いたほうがいい(PushだったりModalのスタックが溜まるのを防ぐ)**

```swift
self.dismiss(animated: true, completion: nil)
```

### Storyboardなしで全てコードで書く場合
#### NCを遷移元に埋め込みsegueでやらずに`init`でやる場合
・AppDelegateに少し書き加える
・遷移先のVCをインスタンス化して

```AppDelegate.swift
 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = MainTabBarViewController()
        window?.makeKeyAndVisible()

        return true
    }
```

```swift
//遷移先 //このinitでtitleName指定の作業が必要なのかは、あとで追記

```

```swift
let vc = SecondViewController(titleName: "second")
navigationController?.pushViewController(vc, animated: true)
```

#### NCでなく各VCに対しnavigationBarを作成する場合
あとで追記

#### NavigationControllerをコードで追加し、後からnavigationBarをコードで設定する
NCに関してStoryboard導入前の`Flag`が使えそうなので例にあげます
・AppDeleteでHomeVCをNCの配下におきます
->`HomeVC`に対しNCを`Embed In`してるのと同じ

```AppDelegate.swift
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?
    var navigationController: UINavigationController?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
       // NavigationControllerの設定
        let homeView: HomeVC = HomeVC()
        navigationController = UINavigationController(rootViewController: homeView)
        navigationController?.interactivePopGestureRecognizer?.isEnabled = true
        self.window = UIWindow(frame: UIScreen.main.bounds)
        self.window?.rootViewController = navigationController
        self.window?.makeKeyAndVisible()
        
        return true
    }
}
```

ここで`navigationBar`の設定
->HomeVCはNC配下にあるので`self.navigationController?.navigationBar`はnavigationBarを参照できる
->`self.navigationItem.title`でtitleを参照できるのも`HomeVC`をNC配下にしたから
->画面遷移によらない(変化しない)要素に関しては一度`rootViewController`に設定を書いてしまえばあとは書かなくていい
->遷移元で指定した**遷移先VCもNC配下になるから**(この辺は`Embed In`したほうがイメージはつきやすい？)
->画面遷移による要素は遷移先のVCで新たに設定を書く必要がある
->NC配下で遷移した場合、遷移先VCの`navigationBar`は**左側ボタンのみ`title+戻るボタン`がつく**のがデフォみたい

・遷移元(`HomeVC`)

```HomeVC.swift
self.navigationItem.title = "Flag"
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white,NSAttributedStringKey.font:UIFont.systemFont(ofSize: 24)]
self.navigationController?.navigationBar.barTintColor = UIColor(hex: "46EA62")
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.tintColor = UIColor.white
        
leftBarButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(HomeVC.tappedLeftBarButton))
rightBarButton = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(HomeVC.tappedRightBarButton))
self.navigationItem.leftBarButtonItem = leftBarButton
self.navigationItem.rightBarButtonItem = rightBarButton
```
<img width="375" alt="Simulator Screen Shot - iPhone 8 - 2019-10-15 at 03.00.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427937/00881318-b7da-f594-a67a-ddf6f95d3eed.png">
・遷移先(`CheckVC`)
遷移先VCでなにも書かないとこうなる
->左側のボタンのみ**戻るボタンがついている**(titleいらないのになぁ、、、)
<img width="375" alt="Simulator Screen Shot - iPhone 8 - 2019-10-15 at 03.00.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427937/2fb67ab1-3edf-41fa-7d6c-aac6b187a070.png">
遷移先VCで一部情報を更新するとこうなる
->右側のボタンで`HomeVC`と同じように**共有ボタンを表示できた**(あとはtitleつきの戻るボタン消したい、、、)

```swift
self.navigationItem.title = "Flag"
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white,NSAttributedStringKey.font:UIFont.systemFont(ofSize: 24)]
rightBarButton = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(HomeVC.tappedRightBarButton))
self.navigationItem.rightBarButtonItem = rightBarButton
```
<img width="375" alt="Simulator Screen Shot - iPhone 8 - 2019-10-15 at 03.02.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427937/e764bc40-d7fe-a544-314c-ab934d8d57cd.png">

遷移先VCでしっかり情報を更新するとこうなる
->左右のボタン共に`HomeVC`と**同じようにボタンを表示できた**

```swift
self.navigationItem.title = "Flag"
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white,NSAttributedStringKey.font:UIFont.systemFont(ofSize: 24)]    
leftBarButton = UIBarButtonItem(barButtonHiddenItem: .Back, target: self, action: #selector(HomeVC.tappedLeftBarButton))
rightBarButton = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(HomeVC.tappedRightBarButton))
self.navigationItem.leftBarButtonItem = leftBarButton
self.navigationItem.rightBarButtonItem = rightBarButton
```

# 参考
**・[Swiftでの画面遷移についてまとめ - Qiita](https://qiita.com/superman9387/items/c006ced215352f28a7b9)**
**・[UINavigationControllerでStoryboardでセグエを繋げずにNavigationBarを表示させる - Qiita](https://qiita.com/KikurageChan/items/b4737f63c4ea7273c3b3)**
**・[Swiftのページ遷移【Navigation Controller】 - Qiita](https://qiita.com/ryu1_f/items/4a0e452e94c9ba609220)**
**・[Storyboard を使わずコードだけで画面を生成、遷移をしてみる - Qiita](https://qiita.com/star__hoshi/items/b38cf99457e781ed7625)**
**・[【iOS】画面遷移の基礎【Swift3.0】 - Qiita](https://qiita.com/fromage-blanc/items/b3cb0e7833a1d5659463)**