どうも松山事務所の石丸です。 現在業務では初めての関数型言語scalaと悪戦苦闘中です! さて、3回に渡ってやってきた画面遷移ですが、今回で終わりにしましょう。
画面遷移1では、メイン画面からヘルプ画面を、ただ表示して戻ってくる実装を行いました。画面遷移2では、メイン画面から編集画面にパラメータを渡すところまでを実装しました。今回は編集画面での編集結果をメイン画面に伝えるところを実装していきます。 調べてみたところ、別画面からの結果を受け取る方法は2パターンあるようです。
ひとつずつやっていきましょう。 開発環境はOS X EI Capitan(ver10.11.3)、Xcode(ver7.2.1)になります。
AppDelegateを経由する方式
AppDelegateにプロパティを用意して、メイン画面と編集画面の両方でそのプロパティを参照する方式です。
アプリケーションの設定など、いろんなところから参照するような値はこの方式が向いていると思います。
というような実装でしょうか。
コードは次のようになります。AppDelegate.swift にプロパティを実装します。
@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? var Text: String = "" ...以下省略 }
getter、setterを用意せず Textプロパティの追加を行いました。メイン画面、編集画面から Textプロパティを読み書きします。
ViewController.swift に AppDelegateの Textプロパティの値を表示するように修正します。
import UIKit class ViewController: UIViewController { @IBOutlet weak var textField: UITextField! @IBAction func tapEditButton(sender: UIButton) { let view = storyboard?.instantiateViewControllerWithIdentifier("editViewController") as! EditViewController //view.text = "真サバの塩焼き!"//textField.text! presentViewController(view, 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. } override func viewWillAppear(animated: Bool) { super.viewDidDisappear(animated) let appDelegate:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate textField.text = appDelegate.Text } @IBAction func backFromHelp(segue: UIStoryboardSegue) { } }
8行目:前回は編集画面を表示する直前に、テキストを渡していましたが、AppDelegateを経由するため不要なのでコメントアウトします。メイン画面からはただ編集画面を表示するだけ。 22行目~26行目:追加した viewWillAppear メソッドは、メイン画面が表示される直前のイベントになります。編集画面で更新された AppDelegateの Textプロパティを再表示する処理になります。 あとは編集画面で AppDelegateの Textプロパティを更新してもらえば完了です。
EditViewController.swift は次のようになります。
import UIKit class EditViewController: UIViewController { //var text = "" // パラメータ受け取り用のプロパティ @IBOutlet weak var editText: UITextField! @IBAction func tapButton(sender: UIButton) { let appDelegate:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate appDelegate.Text = editText.text! dismissViewControllerAnimated(true, completion: nil) } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. //editText.text = text let appDelegate:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate editText.text = appDelegate.Text } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
5行目:textプロパティはメイン画面からパラメータを受け取るために用意しましたが、 AppDelegateを経由する方式では不要になるためコメントアウトします。 9行目~13行目: tapButton メソッドは入力されたテキストを AppDelegateの Textプロパティへ反映する処理と編集画面自身を閉じる処理になります。 15行目~21行目:画面表示時の処理も AppDelegate のTextプロパティの値を表示するように修正して完了です。
呼び出し先から通知してもらう方式
もう1つの方式もやってみます。 今回のアプリだと、メイン画面に結果を受け取るためのメソッドを用意し、編集画面からそのメソッドを呼び出してもらって、編集画面からメイン画面へ結果を渡します。
編集画面には「こういった形で結果を伝えるよ」と結果通知プロトコルを宣言し、フィールドに結果通知プロトコルを用意します。確定ボタンが押されたら、結果通知プロトコルを通して入力された値を通知します。 メイン画面は編集画面の結果通知のプロトコルを実装し、編集画面を呼び出す前に、自分(self)に結果を伝えてねと編集画面のフィールドに自分自身を設定します。 まずはプロトコルを定義する EditViewController.swift から
import UIKit protocol EditViewControllerDelegate{ func editDidFinished(modalText: String?) } class EditViewController: UIViewController { var text = "" // パラメータ受け取り用のプロパティ var delegate: EditViewControllerDelegate! = nil @IBOutlet weak var editText: UITextField! @IBAction func tapButton(sender: UIButton) { delegate.editDidFinished(editText.text) dismissViewControllerAnimated(true, completion: nil) } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. editText.text = text } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
3行目~5行目:結果通知のプロトコルを定義します。このプロトコルは確定ボタンが押されたタイミングで、入力されているテキストをパラメータに呼び出されます。 14行目~17行目: tapButton メソッドの1行目がプロトコルを通しての結果通知処理です。 プロトコルを通じて入力テキストを伝えたら編集画面自身を閉じます。メイン画面からパラメータを受け取る方式は前回実装した処理をそのまま使用します。
次にメイン画面の ViewController.swift を実装していきます。
import UIKit class ViewController: UIViewController, EditViewControllerDelegate { @IBOutlet weak var textField: UITextField! @IBAction func tapEditButton(sender: UIButton) { let view = storyboard?.instantiateViewControllerWithIdentifier("editViewController") as! EditViewController view.text = textField.text! view.delegate = self presentViewController(view, animated: true, completion: nil) } func editDidFinished(text: String?){ textField.text = text } 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. } @IBAction func backFromHelp(segue: UIStoryboardSegue) { } }
ViewControllerに EditViewControllerDelegateを実装します。 13行目~15行目: editDidFinished メソッドが編集画面で確定ボタンが押下された時に呼び出されるメソッドになります。パラメータで入力されたテキストが渡されてくるので、そのまま textFieldに設定します。 9行目:編集画面から呼び出してもらえるように、編集画面の delegateプロパティに自分自身を設定してから編集画面を表示します。
実行
さて実行してみましょう。
編集画面で入力した内容がメイン画面へ伝わっていることを確認できましたね。3回にも渡ってやってきた画面遷移ですが、今回でようやく終わりです。 始めた時は簡単に終わると思っていたのですが、画面遷移だけで3回もかかってしまいました。 今回はここまで。ありがとうございました。