私は最近 ARC を使い始めましたが、それ以来、すべてのメモリの問題を ARC のせいにしています。:) おそらく、あなたは私が間違っていることをよりよく理解するのを助けることができます.
私の現在のプロジェクトは CoreGraphics に関するもので、グラフの描画、サムネイルで満たされたビューなどです。いくつかのゾンビを除いて、手動のメモリ管理を使用しても問題はないと思います...しかし、今のところ、大量のサムネイルを作成したり、もう少し複雑なチャートを再描画しようとすると、アプリケーションがクラッシュするだけです.
Instruments を使用してプロファイリングを行っていると、常駐メモリとダーティ メモリの値が非常に高いことがわかります。ヒープ分析は、かなり驚くべき不規則な成長を示しています...
ほんの数枚のサムネイルを描画すると、常駐メモリが約 200 MB 増加します。すべてが描画されると、メモリは描画前とほぼ同じ値に戻ります。ただし、多くのサムネイルがあると、常駐メモリの値が400 MBを超え、明らかにアプリがクラッシュします。同時に描画されるサムネイルの数 (NSOperationQueue とその maxConcurrentOperationCount) を制限しようとしましたが、大量のメモリを解放するにはもう少し時間がかかるように思われるため、実際には問題は解決しませんでした。
現在、実際のデータは多くの複雑なチャート = 多くのサムネイルで機能するため、私のアプリは基本的に機能しません。
すべてのサムネイルは、ここから取得したこのコードで作成されます: (UIImage のカテゴリ)
+ (void)beginImageContextWithSize:(CGSize)size
{
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
if ([[UIScreen mainScreen] scale] == 2.0) {
UIGraphicsBeginImageContextWithOptions(size, YES, 2.0);
} else {
UIGraphicsBeginImageContext(size);
}
} else {
UIGraphicsBeginImageContext(size);
}
}
+ (void)endImageContext
{
UIGraphicsEndImageContext();
}
+ (UIImage*)imageFromView:(UIView*)view
{
[self beginImageContextWithSize:[view bounds].size];
BOOL hidden = [view isHidden];
[view setHidden:NO];
[[view layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
[self endImageContext];
[view setHidden:hidden];
return image;
}
+ (UIImage*)imageFromView:(UIView*)view scaledToSize:(CGSize)newSize
{
UIImage *image = [self imageFromView:view];
if ([view bounds].size.width != newSize.width ||
[view bounds].size.height != newSize.height) {
image = [self imageWithImage:image scaledToSize:newSize];
}
return image;
}
+ (UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize
{
[self beginImageContextWithSize:newSize];
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
[self endImageContext];
return newImage;
}
それほど多くのメモリを消費しない他の方法はありますか、または ARC を使用するときにコードに何か問題がありますか?
メモリ警告 + クラッシュが発生するもう 1 つの場所は、ビューの再描画が多すぎる場合です。速くする必要はありません。何度でも構いません。クラッシュするまでメモリが積み重なっていきますが、その原因は何かを見つけることができません。(VM Tracker で常駐/ダーティ メモリが増加し、Allocations インストゥルメントでヒープが増加していることがわかります)
私の質問は基本的に次のとおりです。なぜそれが起こっているのかを見つける方法は? 私の理解では、特定のオブジェクトの所有者がいない場合、できるだけ早くリリースされます。私のコードの調査では、発生する理由が見当たりませんが、多くのオブジェクトがまったく解放されていないことが示唆されています。保持サイクルについてはわかりません...
ARC リリース ノートへの移行、ヒープ分析に関する bbum の記事、およびおそらく他の多くの記事を読みました。ARC がある場合とない場合で、ヒープ分析がどうにか異なりますか? 私はその出力で何も役に立たないようです。
アイデアをありがとう。
更新: (全員にすべてのコメントを強制的に読ませず、約束を守るため)
私のコードを注意深く調べて、意味のある場所に @autoreleasepool を追加することで、メモリ消費量が削減されました。最大の問題はUIGraphicsBeginImageContext
、バックグラウンド スレッドからの呼び出しでした。それを修正した後(詳細については@Tammo Freeseの回答を参照)、アプリをクラッシュさせないほどすぐに割り当て解除が行われました。
2 回目のクラッシュ (同じチャートを何度も再描画したことが原因) CGContextFlush(context)
は、描画メソッドの最後に追加することで完全に解決されました。私を恥じてください。
似たようなことをしようとしている人への小さな警告: OpenGL を使用してください。CoreGraphics は、特に iPad 3 では、大きな描画をアニメーション化するのに十分な速度ではありません。