NSMutableArray の再利用
-
22-09-2019 - |
質問
(メモリを節約するために) 既存の 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 を作成すればこの問題を解決できることはわかっていますが、古い配列を再利用できないのはイライラします。何が問題なのでしょうか?
解決
既存のnsmutablearrayを再利用しようとするときに(メモリを保存するため)、いくつかのリーク(楽器によって除かれます)を取得しています。
配列が必要とするメモリの量は非常に少量です。保存されるポインターあたり 4 バイト (32 ビット システムの場合) + わずかなオーバーヘッド。メモリを節約するために配列を再利用することは、よほどの特殊な状況を除いて時間の無駄です。
// release its objects
for(int i = 0; i < [arrayOfImages count]; i++) {
[[arrayOfImages objectAtIndex:i] release];
}
// empty array
[arrayOfImages removeAllObjects];
オブジェクトを保持していないため、オブジェクトを解放すべきではありません。上記の後にアプリがクラッシュしなかったということは、オブジェクトを別の場所に過剰に保持している可能性があることを示しています。
新しいnsmutablearrayを作成して、この問題を終えることができることは知っていますが、古い配列を再利用できないことを悩ませます。何が問題なのでしょうか?
このコードにはメモリ リークとして現れるものは何もありません。ただ反対;オブジェクトを解放しすぎています。
そして上記は、本当に再検討する必要があることを示しています メモリ管理のガイドライン 配列を再利用することと、配列を解放して新しい配列を作成することは、実際にはこの問題とは何の関係もありません。
他のヒント
あなたがこの部分は必要ありません。
// release its objects
for(int i = 0; i < [arrayOfImages count]; i++) {
[[arrayOfImages objectAtIndex:i] release];
}
これは、所有権のルールに反しています。あなたはで画像が保持されませんでした。
[arrayOfImages addObject:[UIImage imageNamed:fileName]];
ので、それらを解放するためにあなたの責任ではありません。それはNSMutableArray
が呼び出されたときにそれらを保持し-addObject
だ、とその同類のNSMutableArray
等が呼び出されたときに、それの-removeObject
の責任はそれらを解放するようにします。システムはこのオーバー解除...
私もXcodeで「ビルドと分析」を実行することをお勧めします。
漏れの機器がわかります。画像のファクト1は、あなたがどこか別の画像を使用したことの手段をリークされた、そしてそこにそれを解放しませんでした - 。それはあなたが存在しないコードを表示することはできませんので、漏れはどこあなたを伝えることはできません。
他の人がこの指摘している事実として、やや-であるように、コードので、驚くべきことは、オブジェクトの上に放出し、墜落しているはずです。しかし、それはクラッシュしませんでしたという事実は、あなたが、アレイからの画像を使用し、それらの上に保持されている他のどこか良い兆候です。