【iOSアプリ】Navigation Controllerで前の画面へ変数の値を持ち帰る方法【Swift】

この記事では、SwiftのNavigation Controllerで前の画面へ戻る時に値を持ち帰る方法を紹介します。

以前、こちらの記事で、Navigation Controllerを使った画面遷移の方法や、次の画面へ変数を渡す方法をご紹介しました。

当然、Navigation Controllerで、前の画面へ戻る時に、変数を持ち帰りたい、ということもありますよね。

ところが、前の画面へ変数を持ち帰る場合は、これまでに比べてプログラムを多く書く必要が出てきます。

次の画面へ遷移する場合は、Segueを使った画面遷移でした。
そのため、Segueから必要情報が取得できましたが、前の画面へ戻る場合は、Segueを使った遷移ではありません。
そのため、以下のような実装をする必要があります。

STEP
前の画面へ戻る処理を、自分で実装する。

Navigation Controllerは前の画面へ戻る処理が自動で用意されていましたね。

ただ、これでは、前の画面へ戻る、という処理を検知できないので、前の画面へ戻る処理を自分で実装します。

STEP
前の画面へ戻る直前に、前の画面へ変数を引き渡す。

前の画面へ戻る処理を自分で実装したので、前の画面へ戻るという動作を検知できるようになりました。

前の画面へ戻る動作を検知したら、戻る直前に、変数を前の画面へ渡す処理を実装します。

この記事は、こちらの実装方法を、ソースコード、Storyboard上の画面付きで紹介しています。

この記事では、最終的に以下のようなツールを作れます。

目次

【準備】ツールの画面を作成する

まずは準備として、これから作るツールの画面を作成しましょう。

Navigation Controllerで遷移する2画面を作成し、以下のように作っていきましょう。

画面機能
1画面目「表示」ボタンを押すと、ラベルに2画面目に入力したテキストを表示する
「移動」ボタンを押すと、次画面へ移動する
2画面目「Back」ボタンを押すと、前画面へ戻る
「テキストフィールド」に入力したテキストを、前画面へ持ち帰る

なお、各画面の作り方の詳細は、この記事の先頭で紹介している別の記事にて詳しく解説しています。

もし、画面の作り方がよく分からない場合は、是非、そちらの記事もご覧になって下さい。

1画面目を作る

まずは、1画面目を作りましょう。

上の表示記載の機能を実装していきます。

STEP
Navigation Controllerを設置

Storyboardに2つのView Controllerを配置し、1画面目にNavigation Controllerを適用しましょう。

STEP
オブジェクトを配置

テキストを表示するためのラベルと、2つのボタンを配置しましょう。

ボタンには、「表示」と「移動」とタイトルをつけておきます。

STEP
Segueで遷移をさせる

「移動」ボタンを引っ張り、移動ボタンをタップした時に2画面目へ遷移するようにしましょう。

表示形式は、「Show」にしておきます。

2画面目を作る

続いて、2画面目も、上に記載の通りに作っていきましょう。

STEP
オブジェクトを配置

テキスト入力を受け付けるため、テキストフィールドを配置しましょう。

Navigation Controllerで前の画面へ戻る処理を実装する方法

まずは、Navigation Controllerでの画面遷移後、前の画面へ戻る処理を実装していきましょう。

せっかくなので、以下のように、Navigation ControllerのデフォルトのBackボタンと同じような戻る処理を、実装してみましょう。

以下の流れで実装していきます。

  • 「Back」ボタンを実装する
  • 前の画面へ戻る処理を実装する
  • 実際に動かしてみる
  • プログラムの処理を考えてみる

「Back」ボタンを実装する

まずはBackボタンを画面上に実装してみましょう。Backボタンは、プログラムから実装します。

2つ目のView Controller用に、SecondViewControllerクラスを作り、以下のように実装します。

ハイライトがついている箇所が、追加したコードです。

import UIKit

class SecondViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        let button = UIButton(type: .system)
        button.addTarget(self, action: #selector(back(_:)), for: .touchUpInside)
        button.setTitle("Back", for: .normal)
        button.setImage(UIImage(systemName: "chevron.backward"), for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
        navigationItem.leftBarButtonItem = .init(customView: button)
    }
    
}

この時点では、button.addTargetの行にエラーが表示されるかもしれませんが、このあと、backメソッドを定義することで解消されますので、問題ありません。

前の画面へ戻る処理を実装する

Backボタンができたので、続いて、戻る処理を実装してみます。

Backボタンを押した時の処理を実装しましょう。

ハイライトがついている箇所が、追加したコードです。

import UIKit

class SecondViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        let button = UIButton(type: .system)
        button.addTarget(self, action: #selector(back(_:)), for: .touchUpInside)
        button.setTitle("Back", for: .normal)
        button.setImage(UIImage(systemName: "chevron.backward"), for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
        navigationItem.leftBarButtonItem = .init(customView: button)
    }
    
    @objc private func back(_ sender: Any) {
        navigationController?.popViewController(animated: true)
    }
}

実際に動かしてみる

前の画面へ戻るプログラムの実装が完了しました。

実際に動かしてみましょう。

以下のように、2つ目のView Controllerと、SecondViewControllerクラスを紐づけてあげましょう。

紐づけが完了したら、シミュレータを起動して、実際に動かしてみましょう。

移動ボタンを押した後、次の画面でBackボタンを押すと、元に戻る動作を確認できましたね。

プログラムの処理を考えてみる

実装したプログラムが何をしているのか、考えてみましょう。

STEP
ボタンの生成

まず、この処理では、表示するボタンを生成しています。

let button = UIButton(type: .system)
button.addTarget(self, action: #selector(back(_:)), for: .touchUpInside)
button.setTitle("Back", for: .normal)
button.setImage(UIImage(systemName: "chevron.backward"), for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 16)

上から順に、以下のように処理をしていますね。

  • ボタンを生成
  • ボタンを押した時に実行するメソッドを指定
  • ボタンのタイトルを「Back」に設定
  • ボタンの画像を指定
  • ボタンのタイトルの文字サイズを指定

なお、ボタンの画像の表示には、SF Symbolという便利なアイコン集を使っています。

こちらはこちらの記事で紹介していますので、興味のある方は、是非ご覧になって下さい。

STEP
ボタンの設置

こちらの処理で、ナビゲーションバーに、Backボタンを表示させていますね。

navigationItem.leftBarButtonItem = .init(customView: button)

こちらは見ての通りで、ナビゲーションバーの左側に、ボタンを配置する、という意味です。

なお、ナビゲーションバーには、マニュアルにも記載の通り、他にも様々は設置パターンがあります。

要素名用途の概要
rightBarButtonItemsナビゲーションバーの右側に要素を設置する
titleViewナビゲーションバーの中央に要素を設置する
leftBarButtonItemsナビゲーションバーの左側に要素を設置する
STEP
戻る処理の実装

こちらの処理で、前の画面へ戻っています。

@objc private func back(_ sender: Any) {
    navigationController?.popViewController(animated: true)
}

popViewControllerを実行すると、今表示されているView Controllerが取り外され、その下の、前に表示されていたView Controllerが表示されます。なので、結果として、前の画面へ戻ることができますね。

なお、前の画面に戻る時、今の画面が下にスライドして遷移しましたよね。

これは、animatedがtrueだからです。animatedをfalseにすると、スライドせず、いきなり、前の画面が表示されるようになります。

Navigation Controllerで前の画面へ変数を持ち帰る方法

前の画面へ戻る処理が実装できたので、いよいよ、前の画面へ戻るのと同時に、前の画面へ変数を持ち帰る処理を実装していきましょう。

以下の流れで実装していきます。

  • ボタンを押すとテキストをラベルに表示するプログラムを作成する
  • 2画面目から1画面目へ変数を持ち帰るプログラムを作成する
  • 実際に動かしてみる
  • プログラムの処理を考えてみる

ボタンを押すとテキストをラベルに表示するプログラムを作成する

まずは、1画面目で、「表示」ボタンを押すと、テキストをラベルに表示するプログラムを作ってみましょう。

1つ目のView Controller用のプログラムに、以下の通りに実装します。

ハイライトがついている箇所が、追加したコードです。

import UIKit

class ViewController: UIViewController {
    
    // テキストを表示するラベル
    @IBOutlet var label: UILabel!
    
    // 次の画面で入力されたテキスト
    var text:String = "Label"

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    @IBAction func tapButton(sender: UIButton) {
        label.text = text
    }
}

2画面目から1画面目へ変数を持ち帰るプログラムを作成する

続いて、2画面目から、1画面目へ変数を持ち帰るプログラムを実装しましょう。

2画面目のテキストフィールドに入力されたテキストを、1画面目の変数「text」へ代入できれば良さそうですね。

2画面目用のSecondViewControllerクラスへ、プログラムを追加していきます。

ハイライトがついている箇所が、追加したコードです。

import UIKit

class SecondViewController: UIViewController {
    
    // テキストフィールド
    @IBOutlet var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        let button = UIButton(type: .system)
        button.addTarget(self, action: #selector(back(_:)), for: .touchUpInside)
        button.setTitle("Back", for: .normal)
        button.setImage(UIImage(systemName: "chevron.backward"), for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
        navigationItem.leftBarButtonItem = .init(customView: button)
    }
    
    @objc private func back(_ sender: Any) {
        let nc = self.navigationController!
        let vc = nc.viewControllers[nc.viewControllers.count - 2] as! ViewController
        vc.text = textField.text!

        navigationController?.popViewController(animated: true)
    }
}

実際に動かしてみる

とうとうプログラムが全て完成しました。

実際に動かしてみる前に、まずは、Storyboard上でプログラムと各要素を紐づけてましょう。

1つ目のView Controller上のLabelとButtonを、プログラムと紐づけます。

2つ目のView Controller上のTextFiledも、プログラムと紐づけましょう。

これで準備は完了です。実際に、シミュレータで動かしてみましょう。

2画面目でテキストを入力した後、1画面目へ戻り、表示ボタンをタップすると、入力したテキストが表示されますね。これで、ツールは完成です!

プログラムの仕組みを考えてみる

実装したプログラムが何をしているのか、考えてみましょう。

今回ポイントとなるのは、こちらの処理ですね。こちらで、前のViewControllerを取得して、変数を代入しています。

let nc = self.navigationController!
let vc = nc.viewControllers[nc.viewControllers.count - 2] as! ViewController
vc.text = textField.text!

特にポイントとなるのが、2行目の処理です。

1行目で取得したUINavigationControllerクラスから、viewControllersプロパティを取得して、操作しています。viewControllersとはなんでしょうか。マニュアルを見てみましょう。

The view controllers currently on the navigation stack.

つまり、viewControllersには、これまで遷移してきた各画面の情報が入っているようです。

The root view controller is at index 0 in the array, the back view controller is at index n-2, and the top controller is at index n-1, where n is the number of items in the array.

1つ前のView Controllerへ戻る場合には、viewControllers配列の、2つ前のView Controllerへ遷移すれば良いようですね。また、例えば、1つ前には、先頭のView Controllerが入っているようです。

これで、プログラムの処理が分かりましたね。

マニュアルに従って、プログラムの2行目で、2つ前のView Controller情報 ( = 1つ前のページの情報 ) を取得し、そのView Controllerへ、変数を渡していたわけです。

また、この処理を応用すれば、トップページや、2つ、3つ前のページへも、変数を渡すプログラムも作れそうですね!

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次