将 UIImage 数据上传到服务器获取内存峰值?

Uploading UIImage data to the server getting memory peaks?

我正在尝试将图像数据上传到服务器,它已成功上传,但每次上传图像时都会出现内存峰值。并且还上传了 20 多张图片导致 App 关闭并收到内存警告。

如何解决这个问题?

编辑: 我正在使用 NSURLConnection。

 image = [params valueForKey:key];
 partData = UIImageJPEGRepresentation([ImageUtility getQualityFilterImage:[params valueForKey:key]], 0.8f);
   if([partData isKindOfClass:[NSString class]])
          partData=[((NSString*)partData) dataUsingEncoding:NSUTF8StringEncoding];
                    [body appendData:partData];
            [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
            [urlRequest setHTTPBody:body];

内存峰值是无害的。当您执行大量上传和下载时,您将获得它们。但是它应该稍后恢复到正常水平,您发布的图像就是这种情况。所以我觉得你的情况是无害的,而且很明显。

你应该只担心当你的应用程序使用内存并且稍后不释放它时...

如果您正在执行大量上传..请查看 this thread 中的答案。

你能展示一下你的代码吗?您是否尝试过 NSURLSession ?如果我使用 NSURLSession 上传照片,内存不会有问题。

        NSURL *url = [NSURL URLWithString:@"SERVER"];

        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];

        NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
        for (UIImage *image in self.arrayImages) {
           UIImage *imageToUPload = image;

           NSData *data = UIImagePNGRepresentation(imageToUPload);

           NSURLSessionUploadTask *task = [session uploadTaskWithRequest:[NSURLRequest requestWithURL:url] fromData:data completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

           }];

           [task resume];
        }

几个想法:

  1. 如果上传多张图片,您可能希望限制同时执行的图片数量。

    例如,这是我的内存,当我发出 20 次上传,每张图片大约 5mb,内存飙升至 113mb:

    但是,如果我将此限制为一次只执行不超过 4 个(使用操作队列),则内存使用量得到改善,最大为 55mb(即超过基线约 38mb):

    其他人建议您可以考虑一次不进行多个上传,这样可以进一步降低峰值内存使用量(在我的示例中,峰值内存使用量为 27mb,仅比基线高 10mb),但要认识到你为此付出了严重的性能损失。

  2. 如果使用 NSURLSession,如果您使用带 fromFile 选项的上传任务而不是将资产加载到 NSData,即使同时执行 4 个任务它使用的内存大大减少,比基线少了不到 1 mb:

  3. 我注意到您正在使用 Xcode 仪表分析内存使用情况。我建议使用 Instruments 的分配工具(如上所示)。我建议这样做的原因不仅是我认为它更准确,而且更重要的是,您似乎有某种记忆模式在执行某些操作后不会完全回落到您的基线。这表明您可能有一些泄漏。并且只有 Instruments 可以帮助您识别这些泄漏。

    我建议观看 WWDC 2013 视频 Fixing Memory Issues or WWDC 2012 video iOS App Performance: Memory,其中说明(除其他外)如何使用 Instruments 识别内存问题。

  4. 我注意到您正在从 UIImage 对象中提取 NSData。我不知道您是如何获取图像的,但是如果它们来自您的 ALAssetsLibrary(或者如果您是从其他资源下载的),您可能想要获取原始资产而不是将其加载到UIImage 然后从中创建一个 NSData。如果您使用 UIImageJPEGRepresentation,您总是要么 (a) 使 NSData 大于原始资产(使内存问题更糟);或 (b) 不必要地降低质量以使 NSData 更小。另外,您删除了大部分元数据。

    如果您必须使用 UIImageJPEGRepresentation(例如,它是通过编程创建的 UIImage),那么就这样吧,做您必须做的。但是,如果您有权访问原始数字资产(例如,请参阅 中的 ALAssetsLibrary 示例),然后执行此操作。可以在不使资产超过其需要的情况下最大化质量。

最重要的是,您首先要确保没有任何内存泄漏,然后您要在任何给定时间尽量减少内存中的内存量(不使用任何 NSData 如果你可以)。