【Swift】Swift入門 ~ NavigationControllerを使ってみる ~
2020.02.05
どうも、むつたくです。
今回も前回に続き、Swiftになります。今回の内容はNavigationControllerについてです。
前回の記事→【Swift】Swift入門 ~ UITableViewを使ってみる ~
NavigationControllerは、複数あるViewControllerを階層的に管理し、画面間を簡単に行き来(ナビゲーション)することができるコントローラになります。
前の画面に戻ることができるボタンを自動配置してくれますし、タイトルも設定することができます。このコントローラも便利だと思います。
今回やること
- NavigationControllerについて
- NavigationControllerの簡単な使い方
- NavigationControllerの配置
- Segueを使用した遷移
- Segueを使用しない遷移
開発環境
- macOS Catalina(10.15.1)
- Xcode 11.3
- Swift 5.1
- Simulater iPhone 11Pro
- iOS 13.3
NavigationController について
NavigationControllerは、冒頭でも説明しましたが、ViewControllerを管理、画面間を行き来するコントローラです。iPhoneの設定アプリ等にも使用されてます。下部画像の赤枠線の部分で、ナビゲーションバーと言います。
ナビゲーションバーの左側をタップすれば、前画面に戻ることもできますし、もちろん右にスワイプでも戻ることが出来ます。また、遷移された画面は、NavigationControllerの管理下になり、スタックされていきます。
では、早速使用していきましょう。
NavigationController の簡単な使い方
タイトル設定
タイトルを設定するには、以下のコードになります。
1 | title = "*************" |
[viewDidLoad]に記載すれば問題ないでしょう。
戻るボタンのテキスト非表示
テキストを非表示にするには、遷移元の画面で以下のコードを記載します。
1 | navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) |
[UIBarButtonItem]のtitleに空文字を設定します。こちらも[viewDidLoad]に記載すれば問題ないでしょう。
また、StoryBordでやる場合は、同様の項目に半角スペースを設定しないといけません。
n画面前に戻る
1つ前や、2つ前、はたまた一番最初の画面に戻りたい場合です。
1 2 3 4 5 6 7 8 9 | // 1つ前 に戻る場合 navigationController?.popViewController(animated: true) // 2つ前 に戻る場合 let index = navigationController!.viewControllers.count - 3 navigationController?.popToViewController(navigationController!.viewControllers[index], animated: true) // 一番最初 に戻る場合 navigationController?.popToRootViewController(animated: true) |
1つ前、一番最初の画面に戻りたい場合は、簡単に実装できますが、2つ以上前の画面に戻る場合は、スタックされた画面数から戻る画面数+1の減算してあげればOKです。
ナビゲーションバーを非表示にする
非表示にさせたい画面で、以下のコードを記載します。
1 | navigationController?.navigationBar.isHidden = true |
ただ、これを実装した場合、全ての画面で非表示になってしまうので、他の画面では、以下のコードを実装すると再表示されます。
1 2 3 | override func viewWillAppear(_ animated: Bool) { navigationController?.navigationBar.isHidden = false } |
NavigationController の配置
ViewControllerに設定
さて、前回は記事では、TavleViewのセルをタップしたら、コンソールにタップした行情報をprint()する処理まで実装しました。今回はそこにNavigationControllerを配置します。
配置するには、まずは配置したいViewControllerを選択します。
次に、[ メニューバー > Editer > Embed In > Navigation Controller ]を順に選択して行くと、指定したViewControllerに配置出来ます。
これでNavigationControllerの配置は完了です。
ついでに初期画面のナビゲーションのタイトルを表示してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // ViewController.swift override func viewDidLoad() { super.viewDidLoad() // ↓追加 title = "駅リスト" // <TableView初期設定> tableView.frame = view.frame tableView.dataSource = self tableView.delegate = self tableView.tableFooterView = UIView(frame: .zero) } |
title = “” でNavigationControllerのタイトルを設定することができます。実行してみましょう。以下のイメージになるかと思います。
画面遷移
Segueを使用した遷移
次は、画面遷移です。まずはSegueを使用した遷移方法からです。
使用するのは、画面遷移に必要な「Segue」、画面遷移を起動する「performSegue」、Segueを使用した画面遷移を検知する「prepare」の3つになります。
まずは、新しいswiftファイルを作成します。「Cocoa Touch Class > (class:)SecondViewController > (Subclass:)UIViewContoller」で作成していきます。
次に、新しいViewControllerをMain.StoryBoardに配置します。配置したら、先ほど作成したswiftファイルと紐付けるため、Identity inspectorのCustomClassを編集します。同様に、IdentityのStoryStoryboard IDも編集し、「Use Storyboard ID」のチェックをOnします。
そうしましたら、TableViewCellを選択して、Controlキーを押しながら、SecondViewにドラッグ&ドロップします。ドロップした先でいくつか選択肢が表示されましたが、今回はNavigationControllerを使用した階層的に管理しているので、「Selection Segue > Show」を選択します。
これで完了です。Buildして実行してみましょう。テーブルセルをタップするとSecondViewと表示された画面に遷移すると思います。ブログ冒頭で記載した様に戻る際は左上の「Back」で前画面に戻ることも出来ますし、右にスワイプでも可能です。
親から子への値渡し
ここからは、コードを書いていく必要があります。また、Segueの種類を変更しなくてはいけないので、Segueを削除します。
まずは、Segueの設定からです。MainのViewController->SecondViewControllerのSegueを削除します。
次に、新しいSegueを作成しますが、コード側で任意のタイミングで遷移させたいので「Manuel Segue > Show」を選択します。
それから、そのSegueをコードから呼び出すのでIndentityを設定します。「showSecondView」とします。
次に、「SecondViewController」です。Labelに親から受け取った駅名を表示したいので、受け取る変数と、変数をLabelのTextに格納する処理を記載します。画像は省きますが、StoryBoardのLabelとSecondViewController.swiftを紐付けてあげて下さい。
1 2 3 4 5 6 7 8 9 10 11 12 13 | // SecondViewController.swift // 親から受け取る変数 var getName: String = "" @IBOutlet weak var stationName: UILabel! override func viewDidLoad() { super.viewDidLoad() // Labelへ格納 self.stationName.text = getName } |
次は、「ViewController」です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // ViewController.seift class ViewController: UIViewController { @IBOutlet weak var tableView: UITableView! // ↓追加 private var stationName: String = "" // ↓追加 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if (segue.identifier == "showSecondView") { let secondVC = segue.destination as! SecondViewController secondVC.getName = self.stationName } } //...以下省略... } |
8行目の変数には、タップされた時にタップ行の駅名を格納します。
11行目の関数[prepare]は、Segueが動作すること(画面遷移)をViewControllerに通知する役割になります。遷移先のControllerを定義し、そのControllerのパブリック変数にタップ行の駅名を格納する処理になります。
ここで注意してほしい事があり、現状は1本しかSegueを使用していないので、if文での分岐は必要ないですが、複数本使用する場合には必ず分岐をさせないと誤った画面遷移になりますので、分岐を忘れない様にして下さい。
次にTableViewのDelegateです。print()は必要ないので削除してあります。
1 2 3 4 5 6 | // ViewController.swift // セルタップ時のイベント func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { self.stationName = tableData[indexPath.section][indexPath.row] performSegue(withIdentifier: "showSecondView",sender: nil) } |
5行目で、画面遷移を実行させてますが、StoryBoardで設定した「showSecondView」のSegueを起動し画面遷移、その間に関数「prepare」がSegueの起動を検知したので、発火した…と言う流れになります。
これが、Segueを使用した画面遷移になります。必要なのは、StoryBoardでSegueを引っ張って、そのSegueにIdentityを設定、どこぞのイベントで画面遷移処理のここでは「performSegue」を使用する。値渡しがある場合は、「prepare」の引数[segue]を使用して値を設定する必要あり…と言った感じで、処理があっちこっちになるので、ちょっと管理が大変かもしれません。
Segueを使用しない画面遷移
次は、Segueを使用しない画面遷移になります。使用するものはNavigationControllerの「pushViewController」の1つです。
StoryBoardにNavigationControllerが配置された状態からスタートします。
swiftファイルで完結します。TableViewのタップイベントに以下のコードを記載します。
1 2 3 4 5 6 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let stationName = tableData[indexPath.section][indexPath.row] let secondVC = self.storyboard?.instantiateViewController(withIdentifier: "SecondView") as! SecondViewController secondVC.getName = stationName self.navigationController?.pushViewController(secondVC, animated: true) } |
3行目で、遷移先のViewControllerを定義します。instantiateViewControllerの引数[withIdentifier]には遷移先のStoryboardIDを記載します。
5行目で、NavigationControllerの[pushViewController]を使用して遷移させます。
結果は、Segueを使用した画面遷移と同じになりますが、簡単に実装でき、コード量もこちらがスッキリします。ただ、StoryBoard上での確認はSegueが無いので出来ず、コードから探す事になるので、複数画面がある場合は、初めて見る方には、ちょっと管理が大変かもしれません。
まとめ
Segueを使用した画面遷移は、視覚的にわかりやすいメリットはありますが、StoryBoardもSwiftファイルもゴニョゴニョしなければいけないと言うデメリットもあります。
Segueを使用しない画面遷移は、StoryBoardの各オブジェクトにIDを割り当てるぐらい、コード量も比較的少なく済み時短にも繋がるメリットはありますが、視覚的に分かりづらい、様々なSwiftファイルを追っかけないといけないと言うデメリットもあります。
どちらも一長一短ですが、ケースバイケースなのかなと思ってます。
と言う事で、今回はNavigationControllerについて紹介していきました。
次回もSwiftの入門記事を書く予定です。
それでは、またの機会に!
↓↓↓ぜひチェックしてください
~提供中のヒューマンセンシング技術~
◆人物検出技術
歩行者・来店者数計測やロボット搭載も
https://humandetect.pas-ta.io
◆視線検出技術
アイトラッキングや次世代UIに
https://eyetrack.pas-ta.io
◆生体判定技術
eKYC・顔認証のなりすまし対策を!
https://bio-check.pas-ta.io
◆目検出技術
あらゆる目周りデータを高精度に取得
https://pupil.pas-ta.io
◆音声感情認識技術
会話から怒りや喜びの感情を判定
https://feeling.pas-ta.io
◆虹彩認証技術
目の虹彩を利用した生体認証技術
https://iris.pas-ta.io