LoginSignup
7
3

More than 5 years have passed since last update.

モーダル(ポップアップ)からコントローラへの値の渡し方

Last updated at Posted at 2019-02-27

モーダル(ポップアップのようなもの)から値を受け取れず、この二日間泥沼にはまっていました。
完全に給料泥棒ですwww

何がしたかったかというと具体的には、ユーザがとあるuiSwitchをオンにしたらモーダルが表示されて、そのモーダルが正常に閉じられたらそのまま、異常な閉じ方をされたらuiSwitchオフに戻すといった処理をしたかったわけです。

状況としては
①mainのコントローラでxibのviewを作成(このview上にuiSwitchがある)
②ユーザがそのスイッチを押してモーダル(storyboard)を開く
③ユーザがモーダルの閉じるボタンを押す
④閉じられたことをxibに伝えてスイッチをオフにする

やりたかったことはこれだけです。

流れとしては、閉じられたという情報を

①モーダルのコントローラ(UIViewControllerを継承)
②→mainのコントローラ(UIViewControllerを継承)
③→xibのコントローラ(UIViewを継承)

と伝えていこうかなと思ったわけです。

まずはお手軽そうな②から③、つまりmainのコントローラからxibへ情報伝達する部分を実装しました。

MainController.swift
class MainController: UIViewController {
    // xibのコントローラをインスタンス化
    let xib = Xib()

    // xibに設置されたuiSwitchをオフに
    func setUISwitchOff(){
        xib.uiSwitch.isOn = false
    }
}
Xib.swift
class Xib: UIView {
    // ↓こいつはviewと紐づいてます
    @IBOutlet weak var uiSwitch: UISwitch!
    }
}

これで、mainのコントローラのsetUISwitchOff()を発動すればいつでもxibのuiswitchをオフにできますね。

では①から②、つまりモーダルからmainのコントローラに情報を伝達するにはどうすればいいのか。

使えそうだと目をつけたのは、

presentingViewController

まんま、今見てるビューを司るコントローラを取得できるやつです。
これを使えばモーダルのコントローラの中でmainコントローラをインスタンス化できるだろうと。

強制ダウンキャストが必要だとのことだったので

ModalController.swift
class ModalController: UIViewController{
    @IBAction func closeBtnAction(_ sender: UIButton) {
        // 閉じるボタンを押されたらモーダルを消します
        self.dismiss(animated: false, completion: nil)

        // メインのコントローラに強制ダウンキャスト
        let originVC = self.presentingViewController as! MainController
        // setUISwitch()を発動してXibのスイッチをオフに!!
        originVC.setUISwitchOff()
    }
}

決まった!!!!

…当然そう甘くはなくて
「navigationControllerをMainControllerにキャストできません」
的なエラーが出ました。

あ、はい

どうしよ

「あ、こいつnavigationControllerなのか!!なんか聞いたことあるぞ!!」

調べました。
そしたらどうやら、navigationControllerの一番上のコントローラを取って来なけりゃいけないらしく

ModalController.swift
class ModalController: UIViewController{
    @IBAction func closeBtnAction(_ sender: UIButton) {
        // 閉じるボタンを押されたらモーダルを消します
        self.dismiss(animated: false, completion: nil)

        // とりあえずキャスト
        let naviVC = self.presentingViewController as! UINavigationController
        // 一番上のコントローラを取得し、そいつはMainControllerだからキャスト!!
        let originVC = naviVC.topViewController as! MainController
        originVC.setUISwitchOff()
    }
}

なんと、これでいけました。

できてしまえば簡単だな

と言いたいところですが、ふつーにわかりにくいと思いました。

もっと簡単なやり方があったんじゃないかと思います。まる

7
3
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
7
3