1

(メモリを節約するために)既存のNSMutableArrayを再利用しようとすると、(Instrumentsによって観察された)いくつかのリークが発生します。

基本的に、私はNSMutableArrayを作成し、それをオブジェクト(UIImages)で埋めて、それを保持する別のオブジェクトに渡します。ただし、NSMutableArrayを再度使用する必要があります。すべてのオブジェクトを解放して空にすると、すべてがうまくいくと思いましたが、Instrumentsは、そのメソッドからCALayerがリークしたオブジェクト(??)を報告します。これは次のようになります。

NSString *fileName;
NSMutableArray *arrayOfImages = [[NSMutableArray alloc] init];

// fill the array with images
for(int i = 0; i <= 7; i++) {
    fileName = [NSString stringWithFormat:@"myImage_%d.png", i];
    [arrayOfImages addObject:[UIImage imageNamed:fileName]];
}

// create a button with the array
aButton = [[CustomButtonClass buttonWithType:UIButtonTypeCustom] 
                   initWithFrame:someFrame
                   imageArray:arrayOfImages];

// release its objects
for(int i = 0; i < [arrayOfImages count]; i++) {
    [[arrayOfImages objectAtIndex:i] release];
}
// empty array
[arrayOfImages removeAllObjects];

// fill it with other images
for(int i = 0; i <= 7; i++) {
    fileName = [NSString stringWithFormat:@"myOtherImage_%d.png", i];
    [arrayOfImages addObject:[UIImage imageNamed:fileName]];
}
// create another button with other images (same array)
aSecondButton = [[CustomButtonClass buttonWithType:UIButtonTypeCustom] 
                   initWithFrame:someFrame
                   imageArray:arrayOfImages];

[arrayOfImages release];

わかりやすくするために、私のボタンの初期化メソッドは次のようになります。

- (id)initWithFrame:(CGRect)frame 
      images:(NSArray *)imageArray
{
    if(self = [super initWithFrame:frame]) {
        myImageArray = [[NSArray arrayWithArray:imageArray] retain];
    }
return self;
}

新しいNSMutableArrayを作成してこの問題を解決できることはわかっていますが、古いアレイを再利用できないのは面倒です。何が問題なのですか?

4

3 に答える 3

6

(メモリを節約するために)既存のNSMutableArrayを再利用しようとすると、(Instrumentsによって観察された)いくつかのリークが発生します。

配列は非常に少量のメモリを使用します。(32ビットシステムで)格納されたポインタあたり4バイト+わずかなオーバーヘッド。アレイを再利用してメモリを節約しようとすることは、最も異常な状況を除いて、時間の無駄です。

// release its objects
for(int i = 0; i < [arrayOfImages count]; i++) {
    [[arrayOfImages objectAtIndex:i] release];
}
// empty array
[arrayOfImages removeAllObjects];

あなたはオブジェクトを保持していなかったので、それらを解放するべきではありません!上記の後でアプリがクラッシュしなかったということは、オブジェクトを別の場所に過剰に保持している可能性があることを示しています。

新しいNSMutableArrayを作成してこの問題を解決できることはわかっていますが、古いアレイを再利用できないのは面倒です。何が問題なのですか?

そのコードには、メモリリークとして発生するものは何もありません。ただ反対; オブジェクトを過剰にリリースしています。

そして、上記は、アレイを再利用するのではなく、アレイを解放して新しいアレイを作成することは実際にはこの問題とは関係がないため、メモリ管理ガイドラインを再検討する必要があることを示しています。

于 2010-01-25T03:53:58.470 に答える
4

この部分は必要ありません:

// release its objects
for(int i = 0; i < [arrayOfImages count]; i++) {
    [[arrayOfImages objectAtIndex:i] release];
}

これは所有権のルールに反します。で画像を保持しませんでした

[arrayOfImages addObject:[UIImage imageNamed:fileName]];

したがって、それらを解放するのはあなたの責任ではありません。呼び出されNSMutableArrayたときにそれらを保持するのはそれであり、そのため、その同類の他の人が呼び出されたときにそれらを解放するのはの責任です。あなたが見つけたリークは、システムがこの過剰リリースによって混乱したためかもしれません...-addObjectNSMutableArray-removeObject

また、XCodeで「ビルドと分析」を実行することをお勧めします。

于 2010-01-24T23:05:22.567 に答える
0

Leaksインスツルメントは、リークしたオブジェクトが最初に割り当てられた場所を示します。画像の1つがリークされたという事実は、画像を別の場所で使用し、そこでリリースしなかったことを意味します-存在しないコードを表示できないため、リークはどこにあるかを教えてくれません。

実際、他の人が指摘しているように、コードはそのままではオブジェクトを過剰にリリースしていてクラッシュするはずなので、これはやや驚くべきことです。しかし、クラッシュしなかったという事実は、アレイからのイメージを使用してそれらを過剰に保持している他の場所での良い兆候です。

于 2010-01-25T04:35:30.040 に答える