swiftを勉強しながらアプリを作っている者です。
メモリ管理を考えた時に循環参照を気にする必要があるかと思うのですが、
これまでそういったことを意識せずにコードを書いていたため、いま見てもどれが循環参照になっているかがわかりません。
見つけるためにはどういった手段が考えられるのでしょうか?
あまり使ったことはありせんが、Instrumentsを地道に見ていくことで見つけられるものなのでしょうか?
教えて頂けますと幸いです。よろしくお願い致します。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答1件
0
ベストアンサー
後から循環参照を見つけるのは結構難しいと思いますが、循環参照を起こす可能性のある危ないコーディングパターンを意識しておけばよいと思います。私は以下のような点に注意しています。
- オブジェクトの親子関係(誰が誰を所持しているか)を明確に意識し、子オブジェクトが親オブジェクトをプロパティで保持しないようにする。delegateのように、親オブジェクトとなる可能性があるものを参照する場合は、weak属性にする。
- ブロックやクロージャ内でselfを参照している場合は、そのブロックやクロージャをプロパティに保持しないようにする。また、ブロックやクロージャをパラメータで受け取るオブジェクトがあれば、そのオブジェクトもプロパティに保持しないようにする。(*1参照) どうしてもプロパティに保持したい場合は、selfをweak属性で参照する。
(*1)例えば、ボタンをタップしたら確認メッセージを出した上で呼び出し元のビューコントローラーに戻るようなモーダルビューコントローラーを作る場合、以下のようにalertControllerをプロパティで保持すると、self→alertController→alertAction→クロージャ→selfの循環参照となり、呼び出し元のビューコントローラーに戻っても、ModalViewControllerは解放されず残ったままとなります。
swift
1import UIKit 2class ModalViewController: UIViewController { 3 var alertController:UIAlertController! 4 @IBAction func pushButton(sender: AnyObject) { 5 alertController = UIAlertController(title: "確認", message: "元の画面に戻ります", preferredStyle: .Alert) 6 let alertAction = UIAlertAction(title: "OK", style: .Default) { (UIAlertAction) -> Void in 7 self.dismissViewControllerAnimated(true, completion: nil) 8 } 9 alertController.addAction(alertAction) 10 presentViewController(alertController, animated: true, completion: nil) 11 } 12}
このケースは、そもそもalertControllerをプロパティで保持する必要はないので、以下のようにローカル変数で定義すればいいだけです。このようにクロージャおよびそれを保持するオブジェクトをプロパティに保持しなければselfの循環参照は発生しません。
swift
1import UIKit 2class ModalViewController: UIViewController { 3 @IBAction func pushButton(sender: AnyObject) { 4 let alertController = UIAlertController(title: "確認", message: "元の画面に戻ります", preferredStyle: .Alert) 5 let alertAction = UIAlertAction(title: "OK", style: .Default) { (UIAlertAction) -> Void in 6 self.dismissViewControllerAnimated(true, completion: nil) 7 } 8 alertController.addAction(alertAction) 9 presentViewController(alertController, animated: true, completion: nil) 10 } 11}
そういうことを考えるよりも、ブロックやクロージャ内でselfを参照する場合は常にweak属性で参照すべきという人もいます。
あまり使ったことはありせんが、Instrumentsを地道に見ていくことで見つけられるものなのでしょうか?
ちょっと古い記事ですが、Instrumentsについては
http://u16suzu.hatenablog.com/entry/2013/11/29/051403
が参考になると思います。
このように、Instrumentsを使えばメモリリークを自動検出して循環参照をわかりやすく図示してくれることがあります。
ただ、完璧ではありません。前述のModalViewControllerの循環参照は自動的には検出してくれませんでした。
でも、メモリ使用状況はよくわかるので、ModalViewControllerの個数が解放されずに増えていく様子はInstrumentsで確認できます。今回紹介した紹介記事やサンプルを使って実際にメモリリークを検出する様子を確認してみることをお勧めします。
投稿2016/03/17 04:21
総合スコア6299
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/03/21 16:49
2016/03/22 02:47
2016/03/22 12:22