Help us understand the problem. What is going on with this article?

【Swift4】次の画面にデータを引き継ぐ5つの方法【Xcode】

More than 1 year has passed since last update.

画面A(背景ピンク)のテキストフィールドの値を、画面B(背景ブルー)のそれぞれのテキストフィールドに異なる方法で受け渡すサンプルアプリを作ってみます。
v5.pngv7.png

プロジェクトの用意

Xcodeにて「Single View Application」 をテンプレに新規プロジェクトを作成します。

ViewController.swift

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var textField:UITextField!

    // for back
    @IBAction func goBack(_ segue:UIStoryboardSegue) {}

    /* 1 ++++++++++++++ */
    @IBAction func byInstantiateViewController(_ sender:UIButton) {
        let next = storyboard!.instantiateViewController(withIdentifier: "nextView") as? NextViewController
        let _ = next?.view // ** hack code **
        next?.textField1.text = textField.text
        self.present(next!,animated: true, completion: nil)
    }

    /* 2 ++++++++++++++ */
    @IBAction func byInstantiateViewController2(_ sender:UIButton) {
        let next = storyboard!.instantiateViewController(withIdentifier: "nextView") as? NextViewController
        self.present(next!,animated: true, completion: { () in
            next?.textField2.text = self.textField.text
        })
    }

    /* 3 ++++++++++++++ */
    /// セグエによる遷移
    @IBAction func byPerformSegue(_ sender:UIButton) {
        performSegue(withIdentifier: "nextSegue", sender: nil)
    }

    /// セグエ実行前処理
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let next = segue.destination as? NextViewController
        let _ = next?.view
        next?.textField3.text = textField.text
    }

    /* 4 ++++++++++++++ */
    @IBAction func byUserDefaults(_ sender:UIButton) {
        UserDefaults.standard.register(defaults: ["textField4":textField.text ?? ""])
        UserDefaults.standard.set(textField.text,forKey:"textField4")
        UserDefaults.standard.synchronize()

        let next = storyboard!.instantiateViewController(withIdentifier: "nextView") as? NextViewController
        self.present(next!,animated: true, completion: nil)
    }

    /* 5 ++++++++++++++ */
    @IBAction func byPropertyAccess(_ sender:UIButton) {
        let next = storyboard!.instantiateViewController(withIdentifier: "nextView") as? NextViewController
        self.present(next!,animated: true, completion: nil)
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

NextViewController.swift

import UIKit

class NextViewController: UIViewController {

    @IBOutlet weak var textField1:UITextField!
    @IBOutlet weak var textField2:UITextField!
    @IBOutlet weak var textField3:UITextField!
    @IBOutlet weak var textField4:UITextField!
    @IBOutlet weak var textField5:UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

    }

    override func viewWillAppear(_ animated: Bool) {
        /// ローカルストレージ(UserDefaults)から値を取得
        guard let obj = UserDefaults.standard.object(forKey: "textField4") else {
            return
        }
        textField4.text = obj as? String

        /// 遷移元ビューコントローラにアクセスして値をセット
        textField5.text = (presentingViewController as? ViewController)?.textField.text

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

ストーリーボード関連

ViewController

Controlを押しながら部品からコードに向かってドラッグします。
x1.png

NextViewController

同様に、Controlを押しながら部品からコードに向かってドラッグします。
x2.png

セグエ

セグエIDを設定します。今回はnextSegueとしました。
v3.png

カスタムクラス

遷移先のビューコントローラクラスにNextViewControllerを割り当てます。
v4.png

解説

1.遷移先のビューコントローラのインスタンスを取得してプロパティにセット(その1)

ViewController
    let next = storyboard!.instantiateViewController(withIdentifier: "nextView") as? NextViewController
    let _ = next?.view // ** hack code **
    next?.textField1.text = textField.text
    self.present(next!,animated: true, completion: nil)

「1-instantiateViewController」ボタン押下時。instantiateViewController()にて遷移先ビューコントローラのインスタンスを取得してそのプロパティにアクセス。
let _ = next?.view はアウトレット変数(textField1)をインスタンスさせるためのハックコードです。

2.遷移先のビューコントローラのインスタンスを取得してプロパティにセット(その2)

ViewController
    let next = storyboard!.instantiateViewController(withIdentifier: "nextView") as? NextViewController
    self.present(next!,animated: true, completion: { () in
       next?.textField2.text = self.textField.text
    })

「2-instantiateViewController2」ボタン押下時。instantiateViewController()にて遷移先ビューコントローラのインスタンスを取得するとこまでは前項と同じですが、present()のコールバックブロックにてプロパティをセットしています。ハックコードが不要となりますが、テキストフィールドがチラつく感じがちょっと。。。

3.遷移先のビューコントローラのインスタンスを取得してプロパティにセット(その3)

ViewController
   performSegue(withIdentifier: "nextSegue", sender: nil)
ViewController
    /// セグエ実行前処理
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let next = segue.destination as? NextViewController
        let _ = next?.view
        next?.textField3.text = textField.text
    }

「3-performSegue」ボタン押下時。セグエ実行前に遷移先インスタンスを取得する方法。performSegue()は内部にてprepare()をコールしますのでこれをオーバーライド。アウトレット変数対策のハックコードが必要です。

4.ローカルストレージを経由

ViewController
    UserDefaults.standard.register(defaults: ["textField4":textField.text ?? ""])
    UserDefaults.standard.set(textField.text,forKey:"textField4")
    UserDefaults.standard.synchronize()

    let next = storyboard!.instantiateViewController(withIdentifier: "nextView") as? NextViewController
    self.present(next!,animated: true, completion: nil)
NextViewController
    /// ローカルストレージ(UserDefaults)から値を取得
    guard let obj = UserDefaults.standard.object(forKey: "textField4") else {
        return
    }
    textField4.text = obj as? String

「4-UserDefaults」ボタン押下時。ローカルストレージに保存して遷移先でロードする方法。そこまでの永続性は必要ないと思いますが参考までに。。。

5.遷移元のビューコントローラのインスタンスを取得

NextViewController
    /// 遷移元ビューコントローラにアクセスして値をセット
    textField5.text = (presentingViewController as? ViewController)?.textField.text

遷移先から遷移元ビューコントローラのインスタンスにアクセスする方法。UIViewControllerのプロパティ、presentingViewControllerには遷移元ビューコントローラのインスタンスが格納されています。ただし、格納タイミングはビュースタック構築後なので、viewDidLoad()内でアクセスしてもnilなので注意が必要です。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away