0

UIScrollView のページとして機能する複数の UIView サブクラスを持つアプリがあります。UIView は前後に移動して、ユーザーにシームレスなエクスペリエンスを提供します。ビューのコンテンツは描画がかなり遅いため、NSOperation サブクラスによるロックによって保護された単一の共有 CGBitmapContext でレンダリングされます - NSOperationQueue で一度に 1 つずつ実行されます - UIImage にラップされ、コンテンツを更新するためにメイン スレッドによって使用されますビューの。

-(void)main {

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];

if([self isCancelled]) {
    return;
}
if(nil == data) {
    return; 
}

// Buffer is the shared instance of a CG Bitmap Context wrapper class
// data is a dictionary
CGImageRef img = [buffer imageCreateWithData:data];
UIImage * image = [[UIImage alloc]initWithCGImage:img];
CGImageRelease(img);

if([self isCancelled]) {
    [image release];
    return;
}

NSDictionary * result = [[NSDictionary alloc]initWithObjectsAndKeys:image,@"image",id,@"id",nil];

// target is the instance of the UIView subclass that will use
// the image
[target performSelectorOnMainThread:@selector(updateContentWithData:) withObject:result waitUntilDone:NO];

[result release];
[image release];

[pool release];
}

メイン スレッドで実行される UIView サブクラスの updateContentWithData: も同様に単純です。

-(void)updateContentWithData:(NSDictionary *)someData {

NSDictionary * data = [someData retain];

if([[data valueForKey:@"id"]isEqualToString:[self pendingRequestId]]) {

    UIImage * image = [data valueForKey:@"image"];
    [self setCurrentImage:image];
    [self setNeedsDisplay];

}

// If the image has not been retained, it should be released together
// with the dictionary retaining it
[data release];
}

サブクラスの drawLayer:inContext: メソッドは、UIImage から CGImage を取得し、それを使用してバッキング レイヤーまたはその一部を更新します。このプロセスには保持または解放は含まれません。

問題は、しばらくするとメモリが不足することです。UIView の数は静的です。CGImageRef と UIImage は正しく作成、保持、およびリリースされます (またはそう思われます)。インスツルメントにはリークは見られません。使用可能な空きメモリが常に低下し、数回上昇してから、アプリケーションが終了するまでさらに低下します。アプリはその前に前述のページの約 2 ~ 300 を循環しますが、大量のページが既に高速でスキミングされた後、または、画像のサイズは最大 3MB で、かなり早い段階で枯渇します。

どんな提案でも大歓迎です。

4

1 に答える 1

0

これは古い投稿だと思いますが、他の人の助けになる場合に備えて....これはメモリの断片化の場合のようです。同じように動作するアプリがあります。アプリによって実際に割り当てられるメモリの量が危険なレベルに達することは決してありませんが、アプリの常駐メモリの量を調べると (Allocations Instrument または Activity Monitor Instrument で VM Tracker スナップショットを使用して)、時間の経過とともに容赦なく上昇します。それほど大きくない一時的なスパイクは、アプリを強制終了します。

問題のアプリは、大量の一時的な割り当てを広範囲のサイズで行うマルチスレッド アプリであり、そのタイミングを予測または制御することはできません。このようなアプリは、不要なメモリ割り当てを解放することに偏執的である必要があります。これは、それ自体がメモリを大量に消費するためではなく、大きな画像が割り当てられたブロックに収まらない穴を作成する可能性があるためです。見過ごされがちな小さな割り当てであっても、断片化では重要です (ただし、低レベルのアロケーターが割り当てをサイズごとにグループ化するため、これはある程度役立ちます)。メモリ ゾーンは、理論的にはフラグメンテーションに対処するのに役立ちますが、少なくとも私の経験では、有効にするのはかなり困難です。また、カスタムの自動解放プールを使用するか、できればできるだけ多くの割り当て/初期化を行い、できるだけ早く解放してください。

于 2011-02-03T21:42:01.900 に答える