图像的核心数据性能问题

时间:2013-11-30 16:10:46

标签: ios performance core-data uiimage

我在Core Data中获取和保存图像时遇到了性能问题。

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

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

  

姓名,地址,图片,详情

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

我将图像存储为Transformable。

我尝试将图像存储为二进制数据并使用UIImagePNGRepresentation来解决问题。然而,问题变得更加严重。

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

4 个答案:

答案 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)

最后我想出了一个方法......(感谢你的所有建议)。

这是我的情况。

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

    1. 提供用户在第一次保存之前裁剪图像。
    2. 我将裁剪的和实际的图像保存在核心数据中。
    3. 当用户查看他的个人资料时显示裁剪的较小尺寸图像。
    4. 仅在用户尝试编辑其图像时显示原始图像(以便他可以再次调整大小)。
    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];
      }
      

答案 2 :(得分:0)

最佳做法通常是将图像保存在应用程序的文档目录(或子目录)中,并将图像文件的名称保存在CoreData中。

答案 3 :(得分:0)

一般来说,我同意@Zaph 如果可以,请将图像保留在CoreData持久存储区之外。

如果您必须将图像存储在CoreData中,我建议从image实体中拼出Profile属性,并将其替换为与ProfileImage实体的关系(以 - 之一)。

这将允许您获取Profile个对象,而无需从磁盘加载图像数据的开销。

此外,如果需要,您将能够在图像数据中进行后台获取(在后台预热协调器缓存,然后仅在主线程上访问),并减少对用户体验的影响。

如果您需要在相同的表格视图中显示图像以及Profile信息(例如),这将无效,因为加载时间将相同(使用拇指)在这种情况下) 您仍然可以执行图像的后台获取(异步加载),但是您必须管理内存消耗,而不是使用获取的结果控制器提供的“强大”功能​​。