2

iOS アプリにメモリの問題があり、それについていくつか質問があります。

まず第一に、私は iOS 6 で作業しており、ARC を使用しています。

今、私の状況を説明しましょう:

私は2つのビューを持っています。最初のビューから、ボタンをタップすると、2 番目のビューを ( and を使用allocしてinit) 作成し、次のコードを使用してモーダルとして表示します。

[self presentViewController:secondView animated:YES completion:^{
        [secondView prepareToDraw];   // Function I use to start my computations and rendering
}];

ある時点で、計算が終了したら、2 番目のビューを閉じて最初のビューに戻りたいと思います。私は2番目のビューからこのコードを使用しています:

[self dismissViewControllerAnimated:YES completion:^{
            [self finished];  // Function I use to free some malloc
}];

Instruments Allocations と Leaks を使用してアプリケーションを実行していますが、Leaks はありません。

これが私のコードですdidReceiveMemoryWarning

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

    if ([self isViewLoaded] && ([[self view] window] == nil)) {
        self.view = nil;

        [self tearDownGL];

        if ([EAGLContext currentContext] == self.context) {
            [EAGLContext setCurrentContext:nil];
        }
        self.context = nil;
    }

    // Dispose of any resources that can be recreated.
    NSLog(@"Resources freed");
}

このtearDownGL関数は、テクスチャ、頂点配列などの OpenGLES リソースを解放します...

アプリケーションを実行すると、最初のビューと 2 番目のビューを何度か切り替えた後、メモリ警告が表示され、アプリケーションがクラッシュします。

ここに私の質問があります:

1-アプリケーションは、コントローラーの UIImage、UIView などを自動的に解放していますか? そうでない場合、ARC を使用しているため、どうすればそれらを解放できますか? 関数も見ましたviewDidUnloadが、ドキュメントにあるように非推奨です:

コントローラーのビューがメモリから解放されたときに呼び出されます。(iOS 6.0 では廃止されました。メモリ不足の状態でビューが消去されなくなったため、このメソッドが呼び出されることはありません。)

しかし、メモリ不足の状態でビューがパージされなくなった場合、アプリケーションのクラッシュを防ぐためにメモリを解放するにはどうすればよいでしょうか? 私は何をすべきか?

2-didReceiveMemoryWarning 2 つのコントローラーの関数にブレークポイントを設定しました。シミュレーターでアプリケーションを実行すると、メモリ警告がシミュレートされます。didReceiveMemoryWarningが2 つのコントローラーに対して 1 回呼び出されていることがわかります。しかし、最初のコントローラーと 2 番目のコントローラーを数回切り替えるとdidReceiveMemoryWarning、最初のビュー コントローラーに対しては 1 回呼び出されますが、2 番目のビュー コントローラーに対しては数回呼び出されます。3 回切り替えると、関数は 3 回呼び出されます。したがって、2 番目のビューを「閉じて」最初のビューに戻ると、2 番目のビューは解放されず、まだ存在していると思います。なんで ?どうすれば強制的に破棄できますか? (もう使用せず、新しいものを作成するので)関数で2番目のView Controllerを作成し、それへの参照を保持しません(クラスに保存されません)。

4

4 に答える 4

1

ブロックを操作するときはいつでも、自己への弱い参照を使用する必要があります。これは保持サイクルにつながる可能性があるためです。したがって、コードを次のように変更します。

__weak typeof(self) blockSelf = self;
[self dismissViewControllerAnimated:YES completion:^{
    [blockSelf finished];  // Function I use to free some malloc
}];

また、何かを解放するためのコードは、dealloc にする必要があります。そのコントローラーの有効期間の終わりにのみ発生する場合は、カスタム メソッドは必要ありません。

あなたの最初の呼び出しも間違っているようです:

[self presentViewController:secondView animated:YES completion:^{
        [secondView prepareToDraw];   // Function I use to start my computations and rendering
}];

prepareToDrawコントローラーが最初に提示されたときに一度だけ発生する場合は、このコードを で実行する必要がありますviewDidLoad。コントローラー自体だけが最初に何をセットアップし、最後にティアダウンする必要があるかを知っている必要があるため、これはアーキテクチャにも役立ちます。

それが役立つことを願っています。おそらく、コードに他の/より多くの問題があります。

于 2013-09-05T08:42:24.767 に答える
1

ARC は、画像、ビューなどが即座にリリースされることを常に意味するわけではありません。最も近いアークプールに追加され、解放されます。アプリケーションがそれを必要とするか、どこかで使用する場合、アプリケーションが終了したときにのみ解放されるメインプールに追加されます。したがって、オブジェクトが目的を果たしたと思われる場合は、オブジェクトを自分で削除することをお勧めします。特に画像の場合、他の場所で使用されているかどうかがわからないため、メモリに残ります。

于 2013-09-05T08:35:33.843 に答える
1

(ARC では、すべての強い参照を nil に設定することを意味します) すべてのメモリ (画像、NSData オブジェクト、配列、モデル レイヤーによって表されるすべてのデータなど) は現在必要ではなく、(簡単に) 再作成することができます。それらは再び使用されます。他のすべてのコードは、プロパティ/iVar がメモリ警告中に解放され、その後再作成される可能性がある場合に、プロパティ/iVar が nil であるかどうかがチェックされるように記述されている必要があります。

私はそれself.viewが処分されるかもしれないオブジェクトの中にあるとは思わない.

UIImageView を表示している可能性があります。これはおそらく UIImage オブジェクトで作成されたものです。UIImageView が表示されている間は、その UIImage がメモリ内にある必要はありません。(UIImageView がまだそれを必要とする場合は、画像自体を保持することを心配する必要がないように、それを保持するか、onw で強力な参照を保持します。) それが解放されるリソースです。

処分資源の中にあるかどうかは、私self.contextには言えません。そうかもしれません。

于 2013-09-05T08:35:58.197 に答える