画面A(背景ピンク)のテキストフィールドの値を、画面B(背景ブルー)のそれぞれのテキストフィールドに異なる方法で受け渡すサンプルアプリを作ってみます。
#プロジェクトの用意
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を押しながら部品からコードに向かってドラッグします。
NextViewController
同様に、Controlを押しながら部品からコードに向かってドラッグします。
###セグエ
セグエIDを設定します。今回はnextSegueとしました。
###カスタムクラス
遷移先のビューコントローラクラスにNextViewControllerを割り当てます。
#解説
1.遷移先のビューコントローラのインスタンスを取得してプロパティにセット(その1)
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)
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)
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
}
「3-performSegue」ボタン押下時。セグエ実行前に遷移先インスタンスを取得する方法。**performSegue()
は内部にてprepare()
**をコールしますのでこれをオーバーライド。アウトレット変数対策のハックコードが必要です。
4.ローカルストレージを経由
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)
/// ローカルストレージ(UserDefaults)から値を取得
guard let obj = UserDefaults.standard.object(forKey: "textField4") else {
return
}
textField4.text = obj as? String
「4-UserDefaults」ボタン押下時。ローカルストレージに保存して遷移先でロードする方法。そこまでの永続性は必要ないと思いますが参考までに。。。
5.遷移元のビューコントローラのインスタンスを取得
/// 遷移元ビューコントローラにアクセスして値をセット
textField5.text = (presentingViewController as? ViewController)?.textField.text
遷移先から遷移元ビューコントローラのインスタンスにアクセスする方法。UIViewControllerのプロパティ、**presentingViewController
**には遷移元ビューコントローラのインスタンスが格納されています。ただし、格納タイミングはビュースタック構築後なので、viewDidLoad()内でアクセスしてもnilなので注意が必要です。