UITabBarControllerを備えたMonoTouchアプリがあり、各タブはUINavigationControllerです。これらの一部は、UITableViewとUIToolbarを追加するUIViewControllerをラップし、その他はDialogViewControllerをラップします。
これまでメモリ/ビュー管理にはあまり注意を払っていませんでしたが(ほとんどシミュレータで実行していました)、実際のデバイスでテストを開始すると、メモリ不足の状態が原因でいくつかの障害に気づきました(たとえば、アプリが終了し、ログから、これより前にDidReceiveMemoryWarningが呼び出されたことがわかりました)。また、GCサイクルが原因であると想定している、アプリの応答性の長時間の一時停止に気付く場合もあります。
これまでのところ、navスタックにプッシュするすべてのDialogViewControllerは、ポップしたときに割り当てられたビューやその他のものをクリーンアップすると想定してきました。しかし、私はそれがおそらくそれほど簡単ではないこと、そして物事に対してDispose()を呼び出し始める必要があることに気づき始めています。
MonoTouchとMT.Dを使用してリソースとメモリを管理する方法のベストプラクティスはありますか?具体的には:
- ポップされた後、DialogViewControllerでDisposeを呼び出す必要がありますか?もしそうなら、これを行うのに最適な場所はどこですか?(ViewDidUnload?DidReceiveMemoryWarning?デストラクタ?)
- DVCは、渡されたRootElementのようなオブジェクトを自動的に破棄しますか、それともこれについて心配する必要がありますか?テーブルセル(StyledStringElementなど)のレンダリングの一部としてロードされるUIImagesはどうですか?
- GCが発生したときに応答性に少し影響を与えないように、コレクションの間隔を広げるためにGC.Collect()を呼び出す必要がある場所はありますか?
- 世代別ガベージコレクターは対話性の問題に役立ちますか?また、本番アプリで使用するのに十分安定していますか?(MonoDevelop 3.0.2 / MT 4.3.3ではまだ「実験的」として請求されていると思います)
- iOSが私のアプリを撃つ可能性を減らすために、DidReceiveMemoryWarningで何をする必要がありますか?非表示の各ViewControllerがこの呼び出しを受け取るように見えるので、そのView Controllerのリソースをクリーンアップする必要があると想定しています...ViewDidUnloadで行うのと同じ種類のことを行う必要がありますか?
- ViewDidUnloadが呼び出されないようです(DidReceiveMemoryWarningを取得した後でも)。実際、ログでそれを見たことはありません。iOSがDidReceiveMemoryWarningの後に常にViewDidUnloadを呼び出した場合、ViewDidUnloadですべてのクリーンアップを実行できます...クリーンアップの責任をViewDidUnloadとDidReceiveMemoryWarningの間で分割する最良の方法は何ですか?
この質問の一般的な性質についてお詫びします-これはホワイトペーパーにとって良いトピックのようですが、何も見つかりませんでした...
更新:質問をより具体的にするために:InstrumentsとXamarin Heapshotプロファイラーを使用した後、ユーザーがナビゲーションスタックをポップしたときにUIViewControllersがリークしていることは明らかです。Rolfがバグを報告しましたこれと2つの重複があるので、これは私だけではなく本当の問題です。残念ながら、リークされたUIViewControllerの適切な回避策は見つかりませんでした。Dispose()を呼び出すのに適した場所が見つかりませんでした。ViewDidLoadによって割り当てられたリソースを解放する自然な場所は、ViewDidUnloadメッセージにありますが、シミュレーターで呼び出されることはないため、メモリーフットプリントは増え続けます。デバイスにはDidReceiveMemoryWarningが表示されますが、iOSが実際にビューをアンロードする保証はなく、ViewDidLoadが再度呼び出される保証もないため、ViewControllerとそのリソースを解放する場所としてこれを使用することには消極的です。いずれか(基になるリソースが破棄された状況に対して防御的にコーディングする必要があるViewDidAppearにつながります)。私'