【问题标题】:UIImage save to PNG cause memory leakUIImage保存为PNG导致内存泄漏
【发布时间】:2016-06-17 01:32:56
【问题描述】:

我想将 NSArray 中的 UIImage 作为 PNG 保存到本地。但是,当我在 for 循环中使用 UIImagePNGRepresentation 时,即使已经有一个 @autoreleasepool,内存也会大大增加。

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];
    }
}

所以我尝试将 UIImage 转换为 CGImageRef 并使用 ImageIO 框架来保存图像。然后使用 CGImageRelease() 在每个循环中释放内存。

-(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);
}

}

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];

} enter image description here 内存减少了,但是,发生了一个新问题。由于过度释放的内存,我的应用程序崩溃了。因为 UIImage 是通过 CGImageRelease() 释放的,但是 ARC 也尝试在 app 结束前向僵尸对象发送 delloc 消息。 如何释放 CGImageRef 但不与 ARC 碰撞?

【问题讨论】:

    标签: ios objective-c memory-leaks uiimage cgimageref


    【解决方案1】:

    不要在 CGImage 属性上调用 CGImageRelease(),因为您的代码不包含该对象的 incr 引用。只有在您的代码在某处显式增加 ref 时,您才会在这种情况下释放。

    【讨论】:

    • 感谢您的回答。但是如果我没有释放CGImageRef,内存会不断增长,我该怎么做才能在每个循环中释放内存?
    • 您在上面发布的代码尝试在未保留图像时使用 CGImageRelease() 释放。首先修复它,然后解决代码中的其他问题。例如,您可以将文件名传递给方法,让该逻辑加载 PNG,然后释放任何持有的 refs。与您现在所做的相反,它将所有解压缩的 PNG 图像保存在内存中。您根本无法同时在内存中保存大量解压缩的图像。解决这个问题,你应该会过得更好。
    猜你喜欢
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 2013-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-06
    相关资源
    最近更新 更多