質問内容
初投稿です。独学でSwiftの開発をしています。
Storyboardを利用したiOSアプリ開発にて、親ビューからモーダルで子ビューを開き、子ビューのボタンが押されると子ビューを閉じて親ビューの表示を更新する、という処理をSwiftで作成しています。
これ自体は実現できているのですが、書き方がメモリリークの原因となる相互参照になってしまっていないか、もしそうであれば良い書き方があれば教えていただければと思っています。
該当のソースコード
①親ビューから子ビューを開く際に、親ビューの関数を子ビューのプロパティに渡す
②子ビューでボタンを押された時に、親ビューから渡された関数が実行される
③親ビューのラベルが更新される
(簡略化していますが、一応以下の記法で狙い通りの動きになっています。)
swift
1 2import UIKit 3 4//親ビュー 5class ParentViewController: UIViewController { 6 @IBOutlet weak var label: UILabel! 7 8 //①遷移時に子に親ビューを更新する関数を渡す 9 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 10 if segue.identifier == "toChild" { 11 if let childVc = segue.destination as? ChildViewController { 12 childVc.update = self.updateParentView 13 } 14 } 15 } 16 17 //③子から親ビューが更新される 18 func updateParentView() { 19 self.label.text = "更新されたよ" 20 } 21} 22 23//子ビュー 24class ChildViewController: UIViewController { 25 @IBOutlet weak var label: UILabel! 26 27 var update = {} 28 29 //②子のボタンを押すと親ビュー更新関数を実行して閉じる 30 @IBAction func button_Pushed(_ sender: Any) { 31 self.update() 32 33 DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { 34 self.dismiss(animated: true, completion: nil) 35 } 36 } 37} 38
試したこと
上記ソースコードだと、関数updateと親ビューインスタンスの循環参照になってしまうのではないか?と懸念しています。
(この部分理解が十分でなく用語が正しくなければすみません。)
もしかして、↓の「改」のようにクロージャーとして子ビューに渡せばいいのかもしれませんが、
同じ関数(上記コードだとupdateParentView関数)を親ビューでも利用したいときなど、
できればこの書き方はしたくないな、という気もしており、上記記法で問題がなければこれでいきたいと思っています。
swift
1 //①遷移時に子に親ビューを更新する関数を渡す「「改」」 2 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 3 if segue.identifier == "toChild" { 4 if let childVc = segue.destination as? ChildViewController { 5 childVc.update = {[weak self] in 6 7 self?.label.text = "更新されたよ" 8 } 9 } 10 } 11 } 12
補足情報(FW/ツールのバージョンなど)
以下の環境を使用しています。
Swift5.4
Xcode12.4
StoryBoard
どうぞよろしくお願いいたします。
回答1件
あなたの回答
tips
プレビュー