我在核心数据中获取和保存图像时遇到性能问题。
我有一个包含用户配置文件的核心数据实体。Profile
包括用户的一张照片和其他详细信息,如姓名、地址等。
例如,实体中的一行如下所示。
名称、地址、图像、详细信息
如果我删除图像,一切都很快。添加图像后,每行大约需要1~5秒才能检索到。时间滞后取决于用户上传的图像的大小(我使用仪器验证了使用和不使用图像所花费的时间)。
我将图像存储为可转换。
我尝试通过将图像存储为二进制数据并使用UIImagePNGRepresentation
来解决这个问题。然而,问题变得更糟了。
如何解决此性能问题?由于应用程序的设计,我想在核心数据中保留图像。
Zaph的答案是可以的。如果图像很大,你应该将它们保存在文件系统中,并使用核心数据只保存有关它们的元信息。
在下面的讨论核心数据-存储图像(iPhone)中可以找到决定图像大小的经验法则。Marcus Zarra描述了做出正确决定的三个主要标准。另一个重要的讨论可以在使用新的外部存储标志在核心数据中存储UIImage中找到。
从iOS 5开始,启用外部存储标志,核心数据根据每个值试探性地决定是将数据直接保存在数据库中,还是将URI存储到它为您管理的单独文件中(来源:苹果文档)。
基于此,您的应用程序的要求是什么?为什么需要在核心数据中维护图像?
您还应该考虑将图像保存在一个单独的实体中,但如果可能的话,我确实建议将它们存储在文件系统中。例如,使用外部存储机制,性能将得到优化,因为Core Data为您管理这一点。我的意思是,苹果的工程师在幕后做了很多工作。所以你可以信任他们
最后我找到了一个方法。。。(谢谢你的建议)。
这就是我的处境。
- 用户可以上传任何照片以显示在其个人资料中
- 用户必须能够随时查看他的个人资料,并且照片应该一直显示
- 从核心检索用户的个人资料图像大约需要1到5秒数据,取决于图像的大小
这就是我所做的
- 为用户提供了在第一次保存图像之前裁剪图像的功能
- 我将裁剪后的图像和实际图像都保存在核心数据中
- 当用户查看他的个人资料时,显示了裁剪后的较小尺寸的图像
- 仅当用户尝试编辑其图像时显示原始图像(以便再次调整大小)
下面是编辑图像的代码。将imagePicker.allowsEditing = YES
设置为显示移动和缩放帧。
- (IBAction)myProfileImageEditButton:(id)sender
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.modalPresentationStyle = UIModalPresentationCurrentContext;
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePicker.delegate = self;
imagePicker.allowsEditing = YES;
[self presentViewController:imagePicker animated:YES completion:nil];
[self finishAndUpdateImage];
}
//当从库中选择图像或从相机中拍摄图像时,会调用此方法。
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
//this line moves your original image into image.
UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
//this line moves your original image into editedImage.
UIImage *editedImage = [info valueForKey:UIImagePickerControllerEditedImage];
//create an NSMutable array myImage and store both original and edited images for later use.
[self.myImages addObject:image];
[self.myImages addObject:editedImage];
[self dismissViewControllerAnimated:YES completion:NULL];
//declare your own updateImage method. Store both image and editedImage in core data (in my case, this is what I wanted. Change it based on your requirement). Retrieve only the smaller sized editedImage when user tries to view again.
[self updateImage];
}
最佳做法通常是将图像保存在应用程序的文档目录(或子目录)中,并将图像文件的名称保存在CoreData中。
总的来说,我同意@Zaph的观点
如果可以的话,请将图像排除在CoreData持久存储区之外
如果您必须将图像存储在CoreData中,我建议从Profile
实体中拼接出image
属性,并将其替换为与ProfileImage
实体(到一个)的关系
这将允许您获取Profile
对象,而无需从磁盘加载图像数据
此外,如果需要,您将能够对图像数据进行后台提取(在后台预热协调器缓存,然后才访问主线程),并减少对用户体验的影响
如果您需要在相同的表视图上显示图像和Profile
信息(例如),这将没有帮助,因为加载时间将相同(在这种情况下使用拇指)
您仍然可以执行图像的后台提取(异步加载),但随后您将不得不管理内存消耗,而不使用提取结果控制器提供的"强大"功能。