一入iOS海iOS点点滴滴iOS开发专题

UIImage存为PNG图片内存增长

2016-06-15  本文已影响983人  韧卓

将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
上一篇下一篇

猜你喜欢

热点阅读