【问题标题】:iPhone Creating custom images causes memory leakingiPhone 创建自定义图像会导致内存泄漏
【发布时间】:2011-12-16 11:48:21
【问题描述】:

我有一个代码,每次用户稍微移动滑块并将其添加到子图层时都会生成新图像。它可以工作,只是它会泄漏内存。我保留了我不应该保留的东西?但是我认为我应该释放一切:

UISlider *slider = (UISlider *)sender;
int progressAsInt = (int)(slider.value);

//add moon mask
UIGraphicsBeginImageContextWithOptions(CGSizeMake(400, 400), NO, 1);
CGContextRef contextRef = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(contextRef, 0, 0, 0, 0.8);
CGContextSetRGBStrokeColor(contextRef, 0, 0, 0, 0.8);
int tempx = progressAsInt;
int x = tempx; 
if (x < 0) {
    isHigherThanHalf = YES;
    x = -tempx;
}
else {
    isHigherThanHalf = NO;
}

CGContextSaveGState(contextRef);
BOOL onlyDrawTopHalf = isHigherThanHalf;
CGFloat halfMultiplier = onlyDrawTopHalf ? -1.0 : 1.0;
CGRect ellipse = CGRectMake(200-x/2, 0, 0+x, 400);

CGRect clipRect = CGRectOffset(ellipse, halfMultiplier * ellipse.size.width / 2, 0);
CGContextClipToRect(contextRef, clipRect);
CGContextFillEllipseInRect(contextRef, ellipse);
CGContextRestoreGState(contextRef);

CGContextSaveGState(contextRef);
onlyDrawTopHalf = !onlyDrawTopHalf;
halfMultiplier = onlyDrawTopHalf ? -1.0 : 1.0;
ellipse = CGRectMake(0, 0, 400, 400);

clipRect = CGRectOffset(ellipse, halfMultiplier * ellipse.size.width / 2, 0);
CGContextClipToRect(contextRef, clipRect);
CGContextFillEllipseInRect(contextRef, ellipse);
CGContextRestoreGState(contextRef);

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
NSData *data = (NSData *)CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
//must free pixels
free(pixels);
pixels = (Byte *)[data bytes];


CGImageRef imageRef = image.CGImage;

// create a new image from the modified pixel data
size_t width                    = CGImageGetWidth(imageRef);
size_t height                   = CGImageGetHeight(imageRef);
size_t bitsPerComponent         = CGImageGetBitsPerComponent(imageRef);
size_t bitsPerPixel             = CGImageGetBitsPerPixel(imageRef);
size_t bytesPerRow              = CGImageGetBytesPerRow(imageRef);

CGColorSpaceRef colorspace      = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo         = CGImageGetBitmapInfo(imageRef);
CGDataProviderRef provider      = CGDataProviderCreateWithData(NULL, pixels, [data length], NULL);

CGImageRef newImageRef = CGImageCreate (
                                        width,
                                        height,
                                        bitsPerComponent,
                                        bitsPerPixel,
                                        bytesPerRow,
                                        colorspace,
                                        bitmapInfo,
                                        provider,
                                        NULL,
                                        false,
                                        kCGRenderingIntentDefault
                                        );
// the modified image
UIImage *newImage   = [UIImage imageWithCGImage:newImageRef];
sublayer2.contents = (id)[newImage CGImage];
[self.view.layer addSublayer:sublayer2];
// cleanup
[data release];
CGColorSpaceRelease(colorspace);
CGDataProviderRelease(provider);
CGImageRelease(newImageRef);

我已经添加了[数据发布],但似乎仍有一些泄漏。

编辑 - 我发现除了 [数据发布] 我还需要通过调用来关闭我的图像上下文 UIGraphicsEndImageContext(); 泄漏已经停止。

【问题讨论】:

  • 出于好奇,分析仪会说什么吗?转到产品 -> 分析。

标签: iphone memory-leaks core-graphics


【解决方案1】:
NSData *data = (NSData *)CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));

数据对象未释放。您有时会使用自动释放图像对象,它可能会导致内存警告。

UIImage *newImage   = [UIImage imageWithCGImage:newImageRef];

最好手动创建对象,然后在完成对象后释放。因为我们永远不知道 autorelase 池何时会耗尽。

【讨论】:

  • 确实 NSData 对象似乎泄漏了,但是,我不确定我是否同意下一个陈述:“我们永远不知道自动释放池何时会耗尽”。事实上,我们确实知道,它会在每个运行循环周期结束时耗尽。这使得在同一范围内使用非常安全。
  • @valentina - 我同意你的观点,自动释放池在每个运行循环结束时都会耗尽。但是如何确保运行循环立即结束并且不需要时间。只是想知道更多关于运行循环和所有请。
  • 当你在当前范围内运行代码时,为什么你会关心运行循环周期何时结束,只要它不会确定结束?你不能确切地知道它什么时候结束,但你也不在乎,它会在所有等待执行的代码都执行完时结束。重点是,只要在同一个作用域内使用自动释放的实例,绝对没有问题。
猜你喜欢
  • 2012-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-26
  • 2011-04-18
  • 2013-05-12
相关资源
最近更新 更多