画面遷移時に次の画面にデータを渡す方法を解説します。
swiftでのデータ渡しにはいくつかの手段がありますが、ここでは遷移先画面のインスタンス変数に値を設定する、ごく一般的な方法を紹介します。
環境
この記事の情報は次のバージョンで動作確認しています。
【Swift】5.0
【iOS】12.2
【macOS】Mojave バージョン 10.14.4
値渡しの基本動作
画面遷移時の値渡しの基本動作は、次の通りです。
- 遷移先のビューコントローラーを取得。
- 遷移先ビューコントローラーのインスタンス変数に値をセットする。
- 画面遷移する。
画面遷移のパターンによって若干コードの書き方に違いはありますが、基本の流れは一緒です。
Segueを使った画面遷移での値渡し
View1のTextFieldに入力した値をView2のLabelに表示する処理を実装してみます。
View2への画面遷移にはSegueを使用します。
サンプルではActionSegueを使っていますが、ManualSegueでも値の受け渡し方法は同様です。
Segueを使った画面遷移の方法がわからない場合は、先にこちらの記事を御覧ください。
遷移元画面(View1)の実装
遷移元画面(View1)の全ソース(View1ViewController.swift)です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import UIKit class View1ViewController: UIViewController { @IBOutlet weak var textField1: UITextField! override func viewDidLoad() { super.viewDidLoad() } // ①セグエ実行前処理 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // ②Segueの識別子確認 if segue.identifier == "toView2" { // ③遷移先ViewCntrollerの取得 let nextView = segue.destination as! View2ViewController // ④値の設定 nextView.argString = textField1.text! } } } |
コメントが振られている行が注目ポイントです。
以降で各行の解説をします。
①セグエ実行前処理
1 2 3 4 |
// ①セグエ実行前処理 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { |
prepare()メソッドは、Segueが実行される前に呼び出されるメソッドです。
Segueを使った画面遷移では、このprepare()メソッドをオーバーライドして値を渡す処理を実装します。
②Segueの識別子確認
1 2 3 4 |
// ②Segueの識別子確認 if segue.identifier == "toView2" { |
segue.identifierを確認して、どのSegueが実行されるのか判断します。
ここでは、id="toView2"のSegueが実行される時に、値の設定処理を実行しています。
③遷移先ViewControllerの取得
1 2 3 4 |
// ③遷移先ViewCntrollerの取得 let nextView = segue.destination as! View2ViewController |
遷移先画面のViewControllerを取得します。View2ViewControllerは遷移先画面のクラス名です。
④値の設定
1 2 3 4 |
// ④値の設定 nextView.argString = textField1.text! |
遷移先画面のインスタンス変数(argString)にテキストボックスの値を設定します。
これでSegue実行前の値設定処理が完了です。
遷移先画面(View2)の実装
遷移先画面(View2)の全ソースです。(View2ViewController.swift)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import UIKit class View2ViewController: UIViewController { // ①引数(文字列) var argString = "" @IBOutlet weak var label1: UILabel! override func viewDidLoad() { super.viewDidLoad() // ②引数をラベルにセット label1.text = argString } @IBAction func backView1(_ sender: Any) { self.dismiss(animated: true, completion: nil) } } |
コメントが振られている2行が注目ポイントです。
①引数(文字列)
1 2 3 4 |
// ①引数(文字列) var argString = "" |
前画面より値を受け取るインスタンス変数を宣言します。
インスタンス変数の型は、受け取る値によって任意に設定します。サンプルではString型の変数 argStringを定義しています。
②引数をラベルにセット
1 2 3 4 |
// ②引数をラベルにセット label1.text = argString |
Labelのテキストに前画面より受け取った値(argString)をセットします。
これで前画面で入力した値が、ラベルテキストに表示されます。
Segueを使わない画面遷移での値渡し
View11で入力した値をView12のLabelに表示する処理を実装します。
View12への画面遷移にはpresent()メソッドを使用します。
present()メソッドを使った画面遷移の方法がわからない場合は、先にこちらの記事を御覧ください。
遷移元画面(View11)の実装
遷移元画面(View11)の全ソースです。(View11ViewController.swift)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import UIKit class View11ViewController: UIViewController { @IBOutlet weak var textField1: UITextField! override func viewDidLoad() { super.viewDidLoad() } // goView12ボタン押下時の処理 @IBAction func goView12(_ sender: Any) { // storyboardのインスタンス取得 let storyboard: UIStoryboard = self.storyboard! // 遷移先ViewControllerのインスタンス取得 let nextView = storyboard.instantiateViewController(withIdentifier: "view12") as! View12ViewController // ①値の設定 nextView.argString = textField1.text! // 画面遷移 self.present(nextView, animated: true, completion: nil) } } |
値渡しに関連するコードはコメントに番号が振られた1行のみです。
①値の設定
1 2 3 4 |
// ①値の設定 nextView.argString = textField1.text! |
present()メソッドを呼び出す前に、遷移先画面のインスタンス変数(argString)にテキストボックスの値を設定します。
present()メッソドを使った画面遷移では、遷移先ビューコントローラーが取得処理されているのが前提となりますので、追加するのはこの1行のみです。
遷移先画面(View12)の実装
遷移先画面の実装内容については、Segueを使った画面遷移の場合と同様の為、解説を省略します。
遷移先がナビゲーションコントローラーの場合
図のように、遷移先画面の間にナビゲーションコントローラーがはさまる場合は、少し工夫が必要です。
遷移元画面(View21)の実装
遷移元画面(View21)の全ソースです。(View21ViewController.swift)
ManualSegue(performSegue)を使った画面遷移のサンプルです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
import UIKit class View21ViewController: UIViewController { @IBOutlet weak var textField1: UITextField! override func viewDidLoad() { super.viewDidLoad() } @IBAction func goView22(_ sender: Any) { // Segueの実行 performSegue(withIdentifier: "toView22", sender: nil) } // ①セグエ実行前処理 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // ②Segueの識別子確認 if segue.identifier == "toView22" { // ③遷移先ViewCntrollerの取得 let nc = segue.destination as! UINavigationController let nextView = nc.topViewController as! View22ViewController // ④値の設定 nextView.argString = textField1.text! } } } |
注目ポイントは次の部分です。
1 2 3 4 5 |
// ③遷移先ViewCntrollerの取得 let nc = segue.destination as! UINavigationController let nextView = nc.topViewController as! View22ViewController |
直接の遷移先(=segue.destination)がNavigationControllerですので、値を設定する為には、その先にあるViewControllerを取得する必要があります。
直接Labalに値を設定できない理由
インスタンス変数に値を設定するのではなく、次のように直接ラベルテキストに値を設定すれば、インスタンス変数を用意する必要が無いため、合理的なように思えます。
1 2 3 |
nextView.label1.text = textField1.text! |
しかし、これは実行時にエラーになります。
遷移先のViewControllerのインスタンスを取得した時点では、 まだラベル部品のインスタンスが存在していない為です。
最後に
画面遷移時の値渡しについて、解説しました。
サンプルでは文字列型の値を渡していますが、配列やStruct、クラス変数等を渡す事も可能です。