##目的
親ビューからモーダル遷移した子ビューで操作を行い、その結果に応じて親ビューの内容を更新させるという処理を行いたかったのですが、Delegateを使う以外に簡単な方法がありましたので書くことにしました!(Delegateまだ理解してない...笑)
実際には、
・親ビューにCollectionViewがある
・モーダル遷移した子ビューでCollectionViewに表示する情報を追加する
子ビューから親ビューに戻った時にCollectionViewのinsertItems()やアニメーションなどを含めたメソッドを実行したかった
やり方を調べているとDelegateを使って処理を委譲するという方法を多くみましたが、このくらいの簡単な処理であればCallBackという方法が簡単だということを知ったので紹介します!
##使うViewController
親:ViewControllr
(ボタンを押すと子ビューにモーダル遷移する)
子:ChildViewController
(ボタンを押すとdismissして子ビューから渡す値で親ビューの関数を実行する)
(今回は子ビューから文字列を渡すだけの簡単な処理になっています)
親ビュー | 子ビュー | 戻った後の親ビュー |
---|---|---|
##画面遷移から戻るときに親ビューの画面を更新する方法
子ビューから親ビューに戻る時に値も一緒に渡したい時もあると思うので、引数がある場合とない場合どちらも紹介します!
###引数がある場合
tableViewやcollectionViewに表示したい値を子ビューからもらってinsertItems()をしたい場合はcallBack()の引数に(text: String)だったり(num: Int)にして、reloadData()やinsertItems()などの処理を関数内に書きます!
class ViewController: UIViewController {
//生成するボタンの宣言
private lazy var button: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Button", for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 30)
button.addTarget(self, action: #selector(tappedButton(_:)), for: .touchUpInside)
button.sizeToFit()
button.center = self.view.center
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.white
self.view.addSubview(button)
}
@objc func tappedButton(_ sender: UIButton) {
let childVC = ChildViewController()
//childVCにあるプロパティにクロージャを渡す
//childTextがchildVCから戻る時に渡される引数です
childVC.childCallBack = { (childText) in
self.callBack(text: childText)
}
present(childVC, animated: true, completion: nil)
}
//画面遷移から戻ってきたときに実行する関数
func callBack(text: String) {
button.setTitle(text, for: .normal)
button.sizeToFit()
button.center = self.view.center
}
}
class ChildViewController: UIViewController {
//クロージャを保持するためのプロパティ
var childCallBack: ((String) -> Void)?
private lazy var childButton: UIButton = {
let childButton = UIButton(type: UIButton.ButtonType.system)
childButton.setTitle("ChiltButton", for: UIControl.State.normal)
childButton.titleLabel?.font = UIFont.systemFont(ofSize: 30)
childButton.addTarget(self, action: #selector(tappendChildButton(_:)), for: .touchUpInside)
childButton.sizeToFit()
childButton.center = self.view.center
return childButton
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.lightGray
self.view.addSubview(childButton)
}
@objc func tappendChildButton(_ sender: UIButton) {
dismiss(animated: true) {
//completionのタイミングでプロパティのクロージャを実行
//親ビューで"ボタン押したよ!"という文字列を表示したい!
self.childCallBack?("ボタン押したよ!")
}
}
}
###引数がないクロージャを渡す場合
tableViewだったりCollectionViewのreloadData()をしたいだけなら、引数がいらないのでcallBack()の中にcollectionView.reloadData()と書くだけで大丈夫です!
@objc func tappedButton(_ sender: UIButton) {
let childVC = ChildViewController()
//childVCにあるプロパティにクロージャを渡す
childVC.childCallBack = { self.callBack() }
present(childVC, animated: true, completion: nil)
}
//画面遷移から戻ってきたときに実行する関数
func callBack() {
button.setTitle("子ビューでボタンが押されたよ!", for: .normal)
button.sizeToFit()
button.center = self.view.center
}
##参考にした記事
画面遷移から戻ってきた時に処理を実行する方法
##さいごに
複雑な処理をしたい場合はDelegateを使って処理を委譲した方が良いと思いますが、reloadData()のような簡単な処理だけならCallBackという方法を使った方が簡単に実現できるみたいです!
もし間違っているところなどありましたら教えていただけると嬉しいです!