0

私はこの質問が何度も聞かれることを知っていますが、私はまだ解決策を見つけていません。私のアプリは、a-> b-> c->d->bの順序でビュー間を移動します。これは、ビュー「d」から常に戻るとは限らず、ビュー「b」にジャンプする必要があることを意味します。問題は、ビュー「c」と「d」のメモリが解放されず、いくつかのループ(b-> c-> d-> b-> c ....)の後にアプリがクラッシュすることです。操作の順序は非常に重要です。私はモーダルセグエでビュー間を移動することに言及する必要があります。私は多くの方法でメモリを解放しようとしました:

  1. DidRecieveMemoryWarningを入れる:_myProperty = nil;
  2. ViewDidUnloadに入れる:_myProperty = nil;
  3. すべてのプロパティをweakに変更します。
  4. @autoreleasepoolでコードをラップします。

何も助けられませんでした、しばらくするとアプリがクラッシュします、どうすれば「強制」によってビューとメモリを解放できますか?

4

4 に答える 4

1

ARCは、OS にすべてのリリースを処理させることによって強制的にリリースしないように作成されました。アプリが使用しているメモリの量を調べるには、 xcode インストゥルメントを使用する必要があります。メモリを肥大化させているように聞こえるので、使用されているメモリの量と、メモリを最適化するために何ができるかを確認して、割り当て容量が許容範囲内に収まるようにすることをお勧めします。(例えば、各画像のサイズが 1Mb のビューに 1000 枚の画像をロードするのは無駄であり、おそらくそのようなクラッシュを引き起こすでしょう。この例は意図的に誇張されているので、理解できるでしょう)

于 2013-02-20T12:27:36.703 に答える
1

Objective-C は (主に) 参照カウント メモリ モデルを使用します。手動参照カウントと自動参照カウント (ARC) があります。

ARC の仕組み

手動で参照カウントを行ったことがあり、clang 静的アナライザー ツールを実行したことがある場合は、それがメモリ リークを見つけるという驚くべき仕事をしていることに気付くでしょう。これが ARC の背後にある考え方です。アナライザーがリークを見つけるのにこれほど優れているのであれば、なぜメモリ管理を実行させないのでしょうか?

したがって、分析はコンパイル時に行われ、結果のコードには保持呼び出しと解放呼び出しが組み込まれます。これが ARC の基盤であり、優れたメモリ モデルであり、パフォーマンスと使いやすさのバランスが取れています。ガベージ コレクションとは異なり、追加の CPU サイクルやバッテリの消耗を必要としないため、モバイル コンピューティングで特に役立ちます。

(注: ARC は弱い参照も導入します。これは、実行時にダングリング ポインターを無効にする方法です)。

ARC の使用は、ガベージ コレクションほど単純ではありません。参照カウント メモリ モデルがどのように機能するかを知る必要があります。次の問題が発生する可能性があります。

保持サイクル

メモリ リークの主な原因は保持サイクルです。これは、オブジェクト A がオブジェクト B への参照を持ち、オブジェクト B がオブジェクト A を参照する場所です。たとえば、AirlineFlight には Passenger が含まれ、Passenger には AirlineFlight -> メモリ リークがあります。

これは、ココアでは非常に一般的です。もう 1 つの例は、ViewController がビューを所有し、View には ViewController であるデリゲートがあります。おなじみですか?

保持サイクルを回避するには、オブジェクトの 1 つが他のオブジェクトを保持しないようにする必要があります。最も一般的な方法は、1 つを親として指定し、もう 1 つを子として指定することです。親は子を保持しますが、子は親を保持しません。例:

ビューコントローラー

@interface MyViewController

@property (nonatomic, strong) MyView* view

@end

意見

@interface MyView

@property (nonatomic, assign) MyViewController* controller

@end

リテイン サイクルが中断され、メモリ リークが発生しなくなりました。

ぶら下がりポインタ

上記の例ではメモリ リークはなくなりましたが、ダングリング ポインターという別の問題が発生する可能性があります。ビューにはコントローラーへの参照がまだ残っていますが、ビューコントローラーはなくなる可能性があります。コントローラーを呼び出すと、クラッシュが発生するようになりました。

これを修正するには、次の 2 つの方法があります。

  1. dealloc メソッドでコントローラーへの参照を nil アウトします。. . しかし、おそらくただ

  2. 次のように弱参照を使用します。

    @property (nonatomic, weak) MyViewController* controller
    

iOS 5 以降 (または OSX 10.7) には、ダングリング ポインターを追跡し、それらを無効にする小さなランタイム ユーティリティがあります。これらは弱参照と呼ばれます。

メモリ リークの検出

いくつかの方法があります。

  • 保持サイクルを検出するには、clang 静的アナライザーを使用します。
  • 楽器ツールを使用する
  • コントローラーやその他の重要なクラスの dealloc メソッドにログ ステートメントを入れて、それらが確実に解放されるようにするのが好きです。

ダングリング ポインターの検索

  • 環境変数 NS_ZOMBIES_ENABLED でコンパイルします (または、Xcode でスキームを編集し、チェックボックスをクリックして、このパラメーターを設定します)。

自動解放プール

発生する可能性のある別の問題は、実行ループ内で割り当てられるオブジェクトが多すぎることです。. これを修正するには、メイン プール内に別の自動リリース プールを作成します。

@autoreleasepool
{

}

(あなたの場合、これは問題ではないと思います)。

于 2013-06-08T04:03:09.157 に答える