我在Core Data中获取和保存图像时遇到了性能问题。
我有一个包含用户个人资料的核心数据实体。 Profile
包括用户的一张照片和他的其他详细信息,如姓名,地址等。
例如,实体中的行如下所示。
姓名,地址,图片,详情
如果删除图像,一切都很快。添加图像后,每行需要大约1~5秒才能检索到。时间延迟取决于用户上传的图像大小(我使用仪器验证了使用和不使用图像的时间)。
我将图像存储为Transformable。
我尝试将图像存储为二进制数据并使用UIImagePNGRepresentation
来解决问题。然而,问题变得更加严重。
如何解决此性能问题?由于应用程序的设计,我想在Core Data中保留图像。
答案 0 :(得分:3)
Zaph的答案还可以。如果图像很大,则应将它们保存在文件系统中,并仅使用Core Data保存有关它们的元信息。
在以下讨论Core Data - Storing Images (iPhone)中可以找到决定图像大小的经验法则。 Marcus Zarra描述了做出正确决定的三个主要标准。另一个重要的讨论可以在Storing UIImage in Core Data with the new External Storage flag中找到。
从iOS 5开始,启用外部存储标记,核心数据启发式地决定是否应该将数据直接保存在数据库中,或者将URI存储到它为您管理的单独文件中。 (来源Apple doc)。
基于此,您的应用有哪些要求?为什么需要在Core Data中维护图像?
您还应该考虑将图像保存在单独的实体中,但我真的建议将它们存储在文件系统中(如果可能的话)。例如,使用外部存储机制,性能将得到优化,因为Core Data会为您管理。我的意思是,Apple工程师在幕后做了很多工作。所以你可以相信他们。 ; - )
答案 1 :(得分:1)
最后我想出了一个方法......(感谢你的所有建议)。
这是我的情况。
这就是我做的事情
以下是编辑图片的代码。设置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];
}
答案 2 :(得分:0)
最佳做法通常是将图像保存在应用程序的文档目录(或子目录)中,并将图像文件的名称保存在CoreData中。
答案 3 :(得分:0)
一般来说,我同意@Zaph
如果可以,请将图像保留在CoreData持久存储区之外。
如果您必须将图像存储在CoreData中,我建议从image
实体中拼出Profile
属性,并将其替换为与ProfileImage
实体的关系(以 - 之一)。
这将允许您获取Profile
个对象,而无需从磁盘加载图像数据的开销。
此外,如果需要,您将能够在图像数据中进行后台获取(在后台预热协调器缓存,然后仅在主线程上访问),并减少对用户体验的影响。
如果您需要在相同的表格视图中显示图像以及Profile
信息(例如),这将无效,因为加载时间将相同(使用拇指)在这种情况下)
您仍然可以执行图像的后台获取(异步加载),但是您必须管理内存消耗,而不是使用获取的结果控制器提供的“强大”功能。