83
94

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-02-23

画面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なので注意が必要です。

83
94
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
83
94

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?