ios - 使用 UIGraphicsBeginImageContext 时内存泄漏

标签 ios objective-c memory-leaks

我尝试一次对超过 100 个 UIimage 进行图像裁剪和羽化。但是在iPhone6上运行时总是会出现内存问题。 Memory Leak checking by Instrucment

这是代码。我怎样才能优化我的代码以最好地使用内存。

-(UIImage*)stitchingImagesNon360:(NSMutableDictionary*) images
{
    UIImage *processImage = [images objectForKey:@"0"];
    processImage= [self rotateImageAppropriately: processImage];
    cropimageWidth=processImage.size.width/factor;

    CGSize size = CGSizeMake(processImage.size.width/factor*(int)images.count, processImage.size.height);
    UIGraphicsBeginImageContext(size);
    @autoreleasepool
    {
        for (int j=0; j<(int)images.count-1; j=j+1)
        {
            NSString* tempIndex=[NSString stringWithFormat:@"%d",j];
            processImage = [images objectForKey:tempIndex];
            processImage= [self rotateImageAppropriately: processImage];

            if (j!=images.count)
            {
                CGRect cropArea= CGRectMake(processImage.size.width*0.5, 0, cropimageWidth*2, processImage.size.height);
                processImage=[self cropImage:processImage cropArea:cropArea];
            }

            if (j!=0)
            {
                processImage=[self featheredImageWithImage:processImage endPoint:cropimageWidth/3];
            }

            CGPoint image1Point = CGPointMake(cropimageWidth*(j), 0);
            [processImage drawAtPoint:image1Point];
            // [cropImage drawAtPoint:image1Point blendMode:kCGBlendModeNormal alpha:1];
        }
    }

    UIImage* stitchedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    images=nil;
    return stitchedImage;

}

CGContextRef ctx;
- (UIImage *) featheredImageWithImage:(UIImage *) image endPoint:     (float) endPointX
{
    @autoreleasepool {

        //  Locations of where the feather starts and ends (0 -> 1)
        const CGFloat featherLocations[] = {1, 0};

        UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);

        ctx = UIGraphicsGetCurrentContext();

        //  Draw the original image
        [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];

        //  A 'knock-out' gradient is used to generate a feather effect,
        //  the alpha channel on the colors defines the alpha of the drawn image
        NSArray *gradientColors = @[(id)[UIColor colorWithWhite:0 alpha:1].CGColor,
                                    (id)[UIColor colorWithWhite:0 alpha:0].CGColor];

        CGGradientRef gradient = CGGradientCreateWithColors(CGImageGetColorSpace(image.CGImage), (__bridge CFArrayRef)gradientColors, featherLocations);

        //  Because we're changing the draw mode below,
        //  take a snapshot of the current draw settings so we can reset them after
        CGContextSaveGState(ctx);

        //  The kCGBlendModeDestinationIn blend mode will provide a'knock-out' effect on
        //  the previously drawn content, using the alpha channels of the gradient's colors
        CGContextSetBlendMode(ctx, kCGBlendModeDestinationIn);

        CGPoint startPoint = CGPointMake(0, 0);
        CGPoint endPoint = CGPointMake(endPointX,  0);
        CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint, 0);

        CGGradientRelease(gradient);
        gradient = NULL;

        CGContextRestoreGState(ctx);

        //  Get the UIImage version
        UIImage *featheredImage = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();
        ctx=nil;

        return featheredImage;
    }
}

- (UIImage *)rotateImageAppropriately:(UIImage *)image
{
    @autoreleasepool {

        CGImageRef imgRef = image.CGImage;
        CGFloat width = CGImageGetWidth(imgRef);
        CGFloat height = CGImageGetHeight(imgRef);
        CGAffineTransform transform = CGAffineTransformIdentity;
        CGRect bounds = CGRectMake(0, 0, width, height);
        CGFloat boundHeight;
        boundHeight = bounds.size.height;
        bounds.size.height = bounds.size.width;
        bounds.size.width = boundHeight;
        transform = CGAffineTransformMakeTranslation(bounds.size.width, 0);
        transform = CGAffineTransformMakeScale(-1.0, 1.0);
        transform = CGAffineTransformRotate(transform, M_PI / 2.0);
        UIGraphicsBeginImageContext(bounds.size);
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextConcatCTM(context, transform);
        CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
        UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();
        //CGImageRelease(imgRef);
        //CGContextRelease(context);
        return imageCopy;
    }
}

最佳答案

有临时内存直到run loop选出才释放。解决这个问题的方法是在循环的内部 添加一个自动释放池。这样,循环的每次迭代都会释放临时内存。

for (int j=0; j<(int)images.count-1; j=j+1)
{
    autoreleasepool {
      /* code */ 
    }
}

您的代码在循环的外部具有自动释放池,并且只会在循环的所有迭代之后释放临时对象。

关于ios - 使用 UIGraphicsBeginImageContext 时内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35191189/

相关文章:

iphone - 我的应用程序崩溃了,但除了数据格式化程序暂时不可用的行之外没有显示任何内容,我现在应该做什么?

c++ - 容器的 Qt 内存管理

Haskell DLL 导致内存泄漏

ios - XCode 4.3.1 iPad模拟器

ios - 用户登录后动态更改登录选项卡和我的个人资料选项卡

ios - 如何使用其他一些参数在服务器的HTTP正文中发送图像

iphone - 使用 AQ 和音频文件流动态检测和流式传输 AAC

ios - UICollectionView 中的 UIImageView 绘制不正确

iphone - 从 iOS 中的 App Delegate 调用当前 View Controller 中的方法

ios - Objective C 中的 NSURL 问题