UIImage存为PNG图片内存增长

将Array中的UIImage取出,存为本地PNG图片

1. UIImage存PNG图片

通过UIImagePNGRepresentation()方法保存PNG格式图片时,由于ARC机制,会产生大量临时的autorelease对象,需要等待runloop的autoreleasepool销毁时才能销毁这些对象。由于for循环中的临时对象无法及时释放,造成内存持续增长,最终导致程序的不稳定,甚至崩溃。

1.1 代码-for循环存PNG图片

objc
for (int i = 0; i < array.count; i++) {

    @autoreleasepool {
        NSDictionary *src = array[i];

        NSString *localPath = [SPLDPath stringByAppendingPathComponent:@"realImg"];
        NSFileManager *file = [NSFileManager defaultManager];
        if (![file fileExistsAtPath:localPath]) {
            [file createDirectoryAtPath:localPath withIntermediateDirectories:NO attributes:nil error:nil];
        }

        NSString *screenShotImg = [localPath stringByAppendingPathComponent:[NSString stringWithFormat:@"ScreenShot_%d.png", i]];
        NSData *PNGData = UIImagePNGRepresentation(src[@"image"]);
        [PNGData writeToFile:screenShotImg atomically:YES];
    }
}

objc

1.2 Instruments中内存持续增长

如下图所示,尽管代码中创建了自己的@autoreleasepool,但是临时对象仍然没有被销毁,仍然以自己的节奏高速增长。


pic1.png

stackoverflow建议

I had the same issue with UIImagePNGRepresentation and ARC. My project is generating tiles and the allocated memory by UIImagePNGRepresentation was just not removed even when the UIImagePNGRepresentation call is part of a @autoreleasepool.

I didn't had the luck that the issue is disappeared by adding a few more @autoreleasepool's like it did for JHollanti.

My solution is based on EricS idea, using the ImageIO Framework to save the png file.

http://stackoverflow.com/questions/9778646/objective-c-uiimagepngrepresentation-memory-issue-using-arc

题主通过增加@autoreleasepool可以释放调用UIImage和UIImagePNGRepresentation来保存PNG图片时,持续增加的内存。但是我们的代码不能释放,回答者DerMarcus建议使用ImageIO框架。

2 ImageIO存PNG图片

2.1 代码

2.1.1 使用ImageIO编写存图方法

objc
-(void)saveImage:(CGImageRef)image directory:(NSString)directory filename:(NSString)filename {
@autoreleasepool {
CFURLRef url = (__bridge CFURLRef)[NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@", directory, filename]];
CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL);
CGImageDestinationAddImage(destination, image, nil);

    if (!CGImageDestinationFinalize(destination))
        NSLog(@"ERROR saving: %@", url);
    
    CFRelease(destination);
    CGImageRelease(image);
}

}
objc

2.1.2 for循环存PNG图片

objc
for (int i = 0; i < array.count; i++) {

   NSDictionary *src = array[i];

   NSString *localPath = [SPLDPath stringByAppendingPathComponent:@"realImg"];
        NSFileManager *file = [NSFileManager defaultManager];
   if (![file fileExistsAtPath:localPath]) {
       [file createDirectoryAtPath:localPath withIntermediateDirectories:NO attributes:nil error:nil];
   }
   NSString *fileName = [NSString stringWithFormat: @"ScreenShot_%d.png", i];
        
   CGImageRef cgRef=[src[@"image"] CGImage];
   [self saveImage:(cgRef) directory:localPath filename:fileName];

}
objc

2.2 Instruments中内存先增后减

注释: 增长峰值为截图产生的内存


pic2.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,211评论 30 472
  • 内存管理 简述OC中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与a...
    丶逐渐阅读 2,008评论 1 16
  • 介绍: UIImageJPEGRepresentation 需要两参数:图片的引用和压缩系数 UIImagePNG...
    rebeccaBull阅读 2,033评论 0 0
  • 1.自定义控件 a.继承某个控件 b.重写initWithFrame方法可以设置一些它的属性 c.在layouts...
    圍繞的城阅读 3,469评论 2 4
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,324评论 25 708