图像的核心数据性能问题



我在核心数据中获取和保存图像时遇到性能问题。

我有一个包含用户配置文件的核心数据实体。Profile包括用户的一张照片和其他详细信息,如姓名、地址等。

例如,实体中的一行如下所示。

名称、地址、图像、详细信息

如果我删除图像,一切都很快。添加图像后,每行大约需要1~5秒才能检索到。时间滞后取决于用户上传的图像的大小(我使用仪器验证了使用和不使用图像所花费的时间)。

我将图像存储为可转换。

我尝试通过将图像存储为二进制数据并使用UIImagePNGRepresentation来解决这个问题。然而,问题变得更糟了。

如何解决此性能问题?由于应用程序的设计,我想在核心数据中保留图像。

Zaph的答案是可以的。如果图像很大,你应该将它们保存在文件系统中,并使用核心数据只保存有关它们的元信息。

在下面的讨论核心数据-存储图像(iPhone)中可以找到决定图像大小的经验法则。Marcus Zarra描述了做出正确决定的三个主要标准。另一个重要的讨论可以在使用新的外部存储标志在核心数据中存储UIImage中找到。

从iOS 5开始,启用外部存储标志,核心数据根据每个值试探性地决定是将数据直接保存在数据库中,还是将URI存储到它为您管理的单独文件中(来源:苹果文档)。

基于此,您的应用程序的要求是什么?为什么需要在核心数据中维护图像?

您还应该考虑将图像保存在一个单独的实体中,但如果可能的话,我确实建议将它们存储在文件系统中。例如,使用外部存储机制,性能将得到优化,因为Core Data为您管理这一点。我的意思是,苹果的工程师在幕后做了很多工作。所以你可以信任他们

最后我找到了一个方法。。。(谢谢你的建议)。

这就是我的处境。

  1. 用户可以上传任何照片以显示在其个人资料中
  2. 用户必须能够随时查看他的个人资料,并且照片应该一直显示
  3. 从核心检索用户的个人资料图像大约需要1到5秒数据,取决于图像的大小

这就是我所做的

  1. 为用户提供了在第一次保存图像之前裁剪图像的功能
  2. 我将裁剪后的图像和实际图像都保存在核心数据中
  3. 当用户查看他的个人资料时,显示了裁剪后的较小尺寸的图像
  4. 仅当用户尝试编辑其图像时显示原始图像(以便再次调整大小)

下面是编辑图像的代码。将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信息(例如),这将没有帮助,因为加载时间将相同(在这种情况下使用拇指)
您仍然可以执行图像的后台提取(异步加载),但随后您将不得不管理内存消耗,而不使用提取结果控制器提供的"强大"功能。

最新更新