モーダル(ポップアップのようなもの)から値を受け取れず、この二日間泥沼にはまっていました。
完全に給料泥棒ですwww
何がしたかったかというと具体的には、ユーザがとあるuiSwitchをオンにしたらモーダルが表示されて、そのモーダルが正常に閉じられたらそのまま、異常な閉じ方をされたらuiSwitchオフに戻すといった処理をしたかったわけです。
状況としては
①mainのコントローラでxibのviewを作成(このview上にuiSwitchがある)
②ユーザがそのスイッチを押してモーダル(storyboard)を開く
③ユーザがモーダルの閉じるボタンを押す
④閉じられたことをxibに伝えてスイッチをオフにする
やりたかったことはこれだけです。
流れとしては、閉じられたという情報を
①モーダルのコントローラ(UIViewControllerを継承)
②→mainのコントローラ(UIViewControllerを継承)
③→xibのコントローラ(UIViewを継承)
と伝えていこうかなと思ったわけです。
まずはお手軽そうな②から③、つまりmainのコントローラからxibへ情報伝達する部分を実装しました。
class MainController: UIViewController {
// xibのコントローラをインスタンス化
let xib = Xib()
// xibに設置されたuiSwitchをオフに
func setUISwitchOff(){
xib.uiSwitch.isOn = false
}
}
class Xib: UIView {
// ↓こいつはviewと紐づいてます
@IBOutlet weak var uiSwitch: UISwitch!
}
}
これで、mainのコントローラのsetUISwitchOff()を発動すればいつでもxibのuiswitchをオフにできますね。
では①から②、つまりモーダルからmainのコントローラに情報を伝達するにはどうすればいいのか。
使えそうだと目をつけたのは、
presentingViewController
まんま、今見てるビューを司るコントローラを取得できるやつです。
これを使えばモーダルのコントローラの中でmainコントローラをインスタンス化できるだろうと。
強制ダウンキャストが必要だとのことだったので
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の一番上のコントローラを取って来なけりゃいけないらしく
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()
}
}
なんと、これでいけました。
できてしまえば簡単だな
と言いたいところですが、ふつーにわかりにくいと思いました。
もっと簡単なやり方があったんじゃないかと思います。まる