2659


<http://qiita.com/osamu1203/items/6dedc01e3b975a0ceec4>

例として上記のようなUIViewController間で値を渡したいときに、デリゲートを使っていますが、デリゲート以外の方法として、どのようなやり方がより簡易にできますか？

ParentViewControllerのインスタンスをModal側で扱えばよいのだと思いますが、どのように書いたらよろしいのでしょうか？

少し曖昧な相談ですが、よろしくお願いします。


CC BY-SA 3.0
2014-12-26T05:23:38.097
2618
2014-12-27T02:14:18.873
2772
question
swift
UIViewController間でのデリゲート以外のイベント通知＆値渡し方法


考えられる方法としては、

  1. NSNotificationCenterを使う
  2. PrepareForSegueで渡す
  3. Singletonクラスから値を取得するようにする

くらいでしょうか。

NSNotificationCenterについては、乱用するとコードが読みづらくなる原因になるので、密接な関係にあるクラス間のメッセージングには利用するべきじゃないかなーと思っています。

PrepareForSegueについては、値渡しできるシチュエーションが限られる（segueの呼び出し時のみ）ので、微妙かもしれません

Singletonの実装は[Swiftでシングルトンパターンを実装する３つの方法](http://qiita.com/susieyy/items/acb3bc80a1dafe64cffd)あたりを確認ください。


CC BY-SA 3.0
2014-12-26T05:42:46.177
2620
2014-12-26T05:42:46.177
351
2618
answer


> ParentViewControllerのインスタンスをModal側で扱えばよいのだと思いますが

という点については、ModelViewController 側で self.presentingViewController
にアクセスすることでそのインスタンスを取得できます。型キャスト（as）は忘れないように。

[code]

    let parentVC = self.presentingViewController as ParentViewController
    let text = parentVC.modalTextLabel.text!
    println(text)
[/code]

しかし、なぜデリゲートのようなパターンがよく使われているかと言えば、処理の実装場所を適切な担当者に振り分けるためですので、モーダル側が親を取得してそこで行うべき処理なのかは十分考える必要があります。


CC BY-SA 3.0
2014-12-26T21:16:32.120
2659
2014-12-26T21:16:32.120
2618
answer


デリゲートより簡易（ほんの少し編集の必要な箇所が減る）な方法としては、Modal 側にコールバック用のクロージャを持たせる、という方法があります。

Parent 側では Modal を表示するときにクロージャを設定し、

[code]

    class ParentViewController: UIViewController {
        func showModal(sender: AnyObject) {
            let modalVC = ModalViewController(nibName: nil, bundle: nil)
            modalVC.completionHandler = { modalText in
                println(modalText)
                self.modalTextLabel.text = modalText
                self.dismissViewControllerAnimated(true, completion: nil)
            };
            self.presentViewController(modalVC, animated: true, completion: nil)
        }
    }
    
[/code]

Modal 側では、必要な処理が終わったらそのクロージャを実行します：

[code]

    class ModalViewController: UIViewController {
        var completionHandler: ((modalText: String) -> Void)? 
        func submit(sender: AnyObject) { {
            if completionHandler != nil {
                completionHandler!(modalText: self.text1.text)
                completionHandler = nil                           // 循環参照を避けるために破棄
            }
        }
    }
    
[/code]

Apple の API での使用例はかなり少ないですが、`SLComposeViewController` などで使われている方法です：
<https://developer.apple.com/library/ios/documentation/NetworkingInternet/Reference/SLComposeViewController_Class/#//apple_ref/occ/instp/SLComposeViewController/completionHandler>


CC BY-SA 3.0
2014-12-27T02:14:18.873
2663
2014-12-27T02:14:18.873
2299
2618
answer