親Controllerから子Controllerへデータを送り、子Controllerを破棄(dismiss)するタイミングでprotocolとdelegateを使い、データを親Controllerに送る処理を最小単位で解説いたします!
UIViewControllerを2つ用意する

まずは、データを送り合うUIViewControllerを2つ用意します。
左側が親・右側が子になります。
親Controllerから子Controllerにデータを送る
まずは、親Controllerから子Controllerにデータを送ります。(こちらは簡単です。)
親Controller(ViewController)にperformSegueとperformSegueを実行したときに動作する関数を記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() } @IBAction func onClickButton(_ sender: Any) { performSegue(withIdentifier: "goToNext", sender: self) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "goToNext" { let nextVC = segue.destination as! NextViewController nextVC.printData = "fromFirstPageMessage" } } } |
onClickButtonアクション(storyboardのbuttonを押したときに実行される関数)が実行されるとperformSegueが実行され、子ViewController(NextViewController)へ遷移します。
その際に、子Controllerのプロパティ(printData)にメッセージ(“fromFirstPageMessage”)を代入します。
親Controllerから受け取ったデータを子Controllerでprintする
1 2 3 4 5 6 7 8 9 10 11 |
import UIKit class NextViewController: UIViewController { var printData : String = "" override func viewDidLoad() { super.viewDidLoad() print(printData) } } |
子Controller側のviewDidLoad()で、親Controllerから受け取ったデータをprintしましょう。
consoleに”fromFirstPageMessage”と表示されることがわかります。
これで、親→子へのデータ伝達は完了しました。
以上のように、親から子へのデータ伝達は簡単です。
しかし、逆方向である子から親へデータを送って、子Controllerを破棄するにはprotocolとdelegateを利用しなければなりません。
子Controllerにprotocolとdelegateを追加する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import UIKit protocol DataReturn { func returnData(data: String) } class NextViewController: UIViewController { var printData : String = "" var delegate: DataReturn? override func viewDidLoad() { super.viewDidLoad() print(printData) } @IBAction func onClickButton(_ sender: Any) { delegate?.returnData(data: "returnData") dismiss(animated: true, completion: nil) } } |
先程のNextViewControllerのソースにprotocolとdelegateを追加して、onClickButtonアクション時に子Controllerを破棄する命令(dismiss)を実行するように変更いたしました。
親Controllerでdelegateを登録する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import UIKit class ViewController: UIViewController, DataReturn { override func viewDidLoad() { super.viewDidLoad() } @IBAction func onClickButton(_ sender: Any) { performSegue(withIdentifier: "goToNext", sender: self) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "goToNext" { let nextVC = segue.destination as! NextViewController nextVC.printData = "fromFirstPageMessage" nextVC.delegate = self // delegateを登録 } } func returnData(data: String) { print(data) } } |
子Controllerからのデータの伝達を受け取るために、ViewControllerにDataReturnプロトコルを登録。
そして、DataReturnプロトコルのreturnDataメソッドを追加しました。
また、子Controllerのdelegateと親Controllerを結びつけるために、
nextVC.delegate = self
という記述も追加してあります。
この状態で、ビルドして、ボタンを押すと、
- 親から子へ遷移時 (“fromFirstPageMessage”)
- 子から親へ遷移時 (“returnData”)
とconsoleに表示されます。
これで、親Controllerからのデータ伝達と、子Controllerからのデータ伝達が完了しました!
protocolとdelegateは複雑で難しいので、理解するのにすごい時間がかかりました。。。