【发布时间】:2014-01-19 00:34:32
【问题描述】:
在我的应用中,用户可以使用 UIImagePickerController 拍摄多张图片,然后这些图片会一张一张地显示在视图中。
我在内存管理方面遇到了一些问题。随着当今手机上的摄像头以百万像素的速度迅速增长,从 UIImagePickerController 返回的 UIImage 会占用大量内存。在我的 iPhone 4S 上,UIImages 大约 5MB;我很难想象它们在新的和未来的模型上会是什么样子。
我的一个朋友说,处理 UIImage 的最佳方法是立即将它们保存到我的应用程序文档目录中的 JPEG 文件中,并尽快释放原始 UIImage。所以这就是我一直在尝试做的。不幸的是,即使在将 UIImage 保存为 JPEG 并且在我的代码中没有留下对它的引用之后,它也不会被垃圾收集。
这是我的代码的相关部分。我正在使用 ARC。
// Entry point: UIImagePickerController delegate method
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
// Process the image. The method returns a pathname.
NSString* path = [self processImage:[info objectForKey:UIImagePickerControllerOriginalImage]];
// Add the image to the view
[self addImage:path];
}
-(NSString*) processImage:(UIImage*)image {
// Get a file path
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
NSString* filename = [self makeImageFilename]; // implementation omitted
NSString* imagePath = [documentsDirectory stringByAppendingPathComponent:filename];
// Get the image data (blocking; around 1 second)
NSData* imageData = UIImageJPEGRepresentation(image, 0.1);
// Write the data to a file
[imageData writeToFile:imagePath atomically:YES];
// Upload the image (non-blocking)
[self uploadImage:imageData withFilename:filename];
return imagePath;
}
-(void) uploadImage:(NSData*)imageData withFilename:(NSString*)filename {
// this sends the upload job (implementation omitted) to a thread
// pool, which in this case is managed by PhoneGap
[self.commandDelegate runInBackground:^{
[self doUploadImage:imageData withFilename:filename];
}];
}
-(void) addImage:(NSString*)path {
// implementation omitted: make a UIImageView (set bounds, etc). Save it
// in the variable iv.
iv.image = [UIImage imageWithContentsOfFile:path];
[iv setNeedsDisplay];
NSLog(@"Displaying image named %@", path);
self.imageCount++;
}
请注意processImage 方法是如何引用 UIImage 的,但它仅将它用于一件事:制作该图像的 NSData* 表示。那么,processImage方法完成后,UIImage应该会从内存中释放出来吧?
我可以做些什么来减少我的应用程序的内存使用量?
更新
我现在意识到分配分析器的屏幕截图将有助于解释这个问题。
【问题讨论】:
-
UIImageView需要多大的图像?根据上面的代码,图像被保存为 jpeg(节省磁盘空间),然后在addImage方法中重新加载。再次加载图像时,图像会与将其保存为 jpeg 之前一样多。如果可能,请在将其保存到磁盘之前重新缩放到适当的大小。 -
确实我正在为 UIImageView 重新加载图像,但 JPEG 表示只有原始大小的 10-15% 左右,所以我仍然应该看到内存减少,正确的?根据 Instruments 的说法,内存使用量在上升后从未下降。
-
@vote539 - 虽然压缩后的 JPEG 只有 10-15% 的大小,但当您重新加载它以在 imageView 中显示时,它需要解压缩,并且内存要求与任何其他图像。根据经验,您可以将其估计为像素 x 颜色 x 每种颜色的位深度。
标签: ios memory-management uiimage automatic-ref-counting uiimagepickercontroller