0

次のコードを使用して、iOS アプリの touchesEnded で描画のスクリーンショットを撮っています。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

    if(_pagessavedbg.count > selectedIndex)
        self.topimage = [_pagessavedbg objectAtIndex:selectedIndex];

    else
        self.topimage = [UIImage imageNamed:@"BlankImage.png"];

    UIImage *bottomimage = [notification.userInfo objectForKey:@"Image"];

    CGSize size = activeView.frame.size;

    NSUInteger width = size.width * 2;
    NSUInteger height = size.height * 2;

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    unsigned char *rawData = malloc(height * width * 4);
    memset(rawData,0,height * width * 4);

    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

    CGRect bounds;
    bounds.origin = CGPointMake(0,0);
    bounds.size = size;

    CGContextScaleCTM(context, 2.0, 2.0);

    CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), [self.topimage CGImage]);
    CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), [bottomimage CGImage]);

    CGImageRef imageRef2 = CGBitmapContextCreateImage(context);
    UIImage *latest2 = [UIImage imageWithCGImage:imageRef2 scale:0.0 orientation:UIImageOrientationDownMirrored];

    activeView.layer.contentsScale = 2.0;
    [activeView.layer renderInContext:context];

    CGImageRef imageRef = CGBitmapContextCreateImage(context);
    UIImage *latest = [UIImage imageWithCGImage:imageRef scale:0.0 orientation:UIImageOrientationDownMirrored];

    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(imageRef);
    CGImageRelease(imageRef2);
    free(rawData);

    [_pages replaceObjectAtIndex:_sidebar.selectedIndex withObject:latest];

    [_sidebar reloadData];

    if(_pages.count > selectedIndex)
    {
    if([_pages objectAtIndex:selectedIndex])
    [_pages replaceObjectAtIndex:selectedIndex withObject:latest];

    if([_pagessavedbg objectAtIndex:selectedIndex])
    [_pagessavedbg replaceObjectAtIndex:selectedIndex withObject:latest2];

    else
    [_pagessavedbg insertObject:latest2 atIndex:selectedIndex];
    }

    dispatch_async(dispatch_get_main_queue(), ^{
    [self.sidebar reloadData];
    [self.sidebar scrollRowAtIndexToVisible:_sidebar.selectedIndex];
    });    


});

ただし、このコードが (touchesEnded で) 呼び出されるたびに、メモリ使用量が約 10MB 増加します。なぜこうなった?これを行うための、より少ないメモリを使用するより良い代替方法はありますか?

4

1 に答える 1

3

Justin が指摘しているように、2048 * 1536 * 4 = 12MB です。その事実は数学であり、避けることはできません。ただし、12MB を割り当てることが問題である場合、メモリ使用率を管理する方法はたくさんあります (1GB デバイスで短期間使用する場合、実際にはそれほど多くのメモリではないため、どのような問題を解決しようとしているのかを確認する必要がありますが、とにかく. ...)

  • これを頻繁に行う場合は、メモリを再割り当てしないでください。再利用してください。そうすれば、一度だけ支払うだけです。
  • 2048*1536*4 の画像が必要ない場合は、より小さなビットマップを作成し、それに収まるように画像をスケーリングします。
  • より小さいビットマップを割り当て、イメージの一部をそれらにレンダリングします。後でそれらを縫い合わせます。

しかし、目標のメモリ割り当てを念頭に置いていますか? Retina ディスプレイは多くのアプリでメモリの大きな問題となっていますが、通常、12MB の割り当てが短時間であれば問題はありません。多くの場合、メモリではなく所要時間です。

ただし、2048*1536*4 のビットマップが必要な場合は、12MB のメモリが必要になります。

于 2012-10-31T02:10:20.753 に答える