iPhone Создание пользовательских изображений вызывает утечку памяти - PullRequest
0 голосов
/ 16 декабря 2011

У меня есть код, который генерирует новое изображение каждый раз, когда пользователь немного перемещает ползунок и добавляет его в подслой.Это работает, за исключением утечки памяти.Что я сохраняю, что не должен?Тем не менее, я думаю, что я выпускаю все, как я должен:

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 ();Утечки прекратились.

1 Ответ

0 голосов
/ 16 декабря 2011
NSData *data = (NSData *)CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));

объект данных не освобожден. вы используете объект autorelease изображения, иногда это может привести к предупреждению памяти.

UIImage *newImage   = [UIImage imageWithCGImage:newImageRef];

Всегда лучше создать объект вручную, а затем отпустить, когда вы закончите с объектом. потому что мы никогда не знаем, когда пойдет автопереключение.

...