我正在尝试将图片数据上传到服务器,上传成功,但每张图片上传时内存达到峰值。此外,还上传了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];
答案 0 :(得分:2)
有几点想法:
如果要上传多张图片,您可能需要约束同时执行的图像数量。
例如,这是我的记忆,当我发布20张每张图片大约5mb的内容时,内存飙升至113 MB:
但是,如果我将此限制为一次不超过4次(使用操作队列),则内存使用量会有所改善,最大值为55mb(即基线大约为38mb):
其他人建议您可以考虑一次不要进行多次上传,这进一步降低了峰值内存使用量(在我的示例中,峰值内存使用量为27mb,仅超过基线10mb),但认识到你为此付出严重的性能损失。
如果使用NSURLSession
,如果您在上传任务时使用fromFile
选项,而不是将资产加载到NSData
,即使同时执行4次,也会大大减少使用NSData
内存,比基线小不到1 MB:
我注意到您正在使用Xcode仪表来分析内存使用情况。我建议使用Instruments的Allocations工具(如上所示)。我建议这样做的原因不仅是我认为它更准确,更重要的是,你似乎有一些记忆模式在执行某些动作后没有完全回落到你的基线。这表明您可能有一些泄漏。只有仪器才能帮助您识别这些泄漏。
我建议观看WWDC 2013视频Fixing Memory Issues或WWDC 2012视频iOS App Performance: Memory,其中说明了(如此)如何使用工具识别内存问题。
我注意到您从UIImage
对象中提取ALAssetsLibrary
。我不知道你是如何获取图像的,但是如果它们来自你的UIImage
(或者你是从其他资源下载的那些),你可能想要获取原始资产而不是将其加载到NSData
然后从中创建UIImageJPEGRepresentation
。如果您使用NSData
,则总是要么(a)使NSData
大于原始资产(使内存问题更严重);或(b)不必要地降低质量,以使UIImageJPEGRepresentation
更小。此外,您还要删除大部分元数据。
如果你必须使用UIImage
(例如,它是以编程方式创建的ALAssetsLibrary
),那么就这样吧,做你必须做的事情。但是,如果您有权访问原始数字资产(例如,请参阅NSData
以获取{{1}}示例),那么请执行此操作。在不使资产大于其需要的情况下,可以最大化质量。
最重要的是,您首先要确保没有任何内存泄漏,然后您希望在任何给定时间最小化内存容量(如果可以的话,不要使用任何{{1}} )。
答案 1 :(得分:1)
内存峰值无害。当您执行繁重的上传和下载时,您将获得它们。但它应该会在以后恢复到正常水平,就像你发布的图像一样。所以我认为在你的情况下它是无害的和明显的。
您应该只在应用程序使用内存时才会担心,并且以后不会释放它...
如果您正在执行大量上传..请查看this thread中的答案。
答案 2 :(得分:0)
你能展示你的代码吗?你尝试过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];
}