web-dev-qa-db-ja.com

Swiftで強い参照サイクルを特定するにはどうすればよいですか?

Swiftコードで強い参照サイクルを見つけるためのツールまたは方法はありますか?

強力な参照サイクルとは、クラスの2つのインスタンスが適切な安全性(weak/unowned)なしで相互に参照するため、作成したすべての変数がそれらの参照を停止すると、ガベージコレクターがそれらを破棄できなくなります。オブジェクト。

24

強い参照サイクルを見つける方法は、Objective-Cの場合と同様にSwiftでも同じです。

Xcodeからアプリを実行し、サイクルを明示するためにアプリを十分に実行してから、「デバッグメモリグラフ」ボタンをタップします( debug memory graph )。次に、左側のパネルでリリースされていないオブジェクトを選択すると、メモリグラフが表示されます。これは、多くの場合、明確な参照サイクルになり得ます。

debug memory graph

ときどき、メモリサイクルはそれほど明確ではありませんが、少なくとも、問題のオブジェクトへの強い参照を保持しているオブジェクトを確認できます。必要に応じて、逆方向に追跡し、その参照を維持しているものを特定できます。

場合によっては、どの種類のオブジェクトが強い参照を保持しているのかを知るだけでは不十分であり、強い参照が確立されたコードのどこにあるのかを本当に知りたい場合があります。 https://stackoverflow.com/a/30993476/1271826 に示されている「malloc stack」オプションを使用して、この強い参照が確立されたときのコールスタックを特定できます(多くの場合、これらの強力な参照が確立された正確なコード行を特定します)。詳細については、WWDC 2016ビデオ Xcodeによるビジュアルデバッグ を参照してください。

Instrumentsを使用して、リークしたオブジェクトを特定することもできます。 Allocationsツールを使用して、Instrumentsを介してアプリを実行し、繰り返し(1回または2回ではなく)アプリを一定の状態に戻します。メモリが増加し続ける場合は、強い参照サイクルがある可能性があります。割り当てツールを使用して、解放されていないオブジェクトの種類を識別したり、「レコード参照カウント」機能を使用して、これらの強い参照が確立された場所を正確に識別したりできます。

メモリの問題の特定と解決の概要については、WWDC 2013ビデオ メモリの問題の修正 およびWWDC 2012ビデオ iOSアプリのパフォーマンス:メモリ を参照してください。ここで提案されている基本的な手法は現在でも適用できます(InstrumentsツールのUIは少し変更されていますが...少し変更されたUIの紹介が必要な場合は、WWDC 2014ビデオを参照してください Insproving Your App with Instruments ) 。

余談ですが、「ガベージコレクション」は非常に異なるメモリシステムを指し、ここでは適用されません。

29
Rob

オブジェクトが割り当て解除されたときに呼び出されるdeinit関数をクラスに追加できます。

Deinitが呼び出されない場合、アプリの実行中に、[デバッグメモリグラフ]ボタン(下に丸で囲まれています)を押して、何が何を参照しているかを調べることができます。

Debug Memory Graph Button

中央のペインの上部にあるドロップダウンメニューを使用して、クラスとクラスのインスタンスを切り替えます。

解放されずに何かが何度も割り当てられている場合は、複数のインスタンスが表示され、その子の1つがその親への強い参照を保持しているかどうかを方向グラフで確認できるはずです。

27
texuf

機器を使用して、リークやメモリ損失をチェックします。 InstrumentsのAllocationsインストゥルメントでMark Generation(Heapshot)を使用します。

Heapshotを使用してメモリクリープを見つける方法については、以下を参照してください bbum blog

基本的には、Instruments allocateツールを実行し、ヒープショットを取得し、コードの反復を実行し、3回または4回繰り返す別のヒープショットを取得する方法です。これは、割り当てられ、反復中に解放されていないメモリを示します。

結果を把握するには、個々の割り当てを確認してください。

オブジェクトの保持、解放、自動解放が発生する場所を確認する必要がある場合は、計測器を使用します。

インストゥルメントで実行し、アロケーションで「レコード参照カウント」をオンに設定します(Xcode 5以下の場合、オプションを設定するには記録を停止する必要があります)。アプリを実行し、記録を停止し、ドリルダウンすると、すべての保持、リリース、自動リリースが発生した場所を確認できます。

1
zaph

Instruments でできます。 この記事 の最後の段落は次のように述べています:

Instrumentsが開いたら、アプリケーションを起動して、特にテストする領域またはビューコントローラでいくつかの操作を行う必要があります。検出されたリークは、「リーク」セクションに赤い線で表示されます。アシスタントビューには、リークに関連するスタックトレースをInstrumentsが表示する領域が含まれ、問題がどこにあるかについての洞察を与え、問題のあるコードに直接移動することもできます。

0
pxlshpr

非常に簡単なアプローチは、プリントをdeinitialiserに置くことです

deinit {
   print("<yourviewcontroller> destroyed.")
}

この行がコンソールに出力されていることを確認してください。すべてのビューコントローラーにdeinitを配置します。特定のビューコントローラーを表示できなかった場合は、それらが参照サイクルであることを意味します。考えられる原因は、デリゲートが強い、自己をキャプチャするクロージャー、侵入されていないタイマーなどです。

0