在 NSAttributedString 中添加图像并保存到 Core Data 性能

Posted

技术标签:

【中文标题】在 NSAttributedString 中添加图像并保存到 Core Data 性能【英文标题】:Add images in NSAttributedString and save to Core Data peformance 【发布时间】:2017-04-17 15:06:05 【问题描述】:

我在将包含图像的 NSAttrbutedString 保存到 Core Data 时遇到了这个巨大的性能问题。

有一个 UITextView 允许用户输入文本以及添加图像。当用户完成输入并单击“完成”按钮时,它将被保存到 CoreData,并显示在 TableView 中。

点击“完成”按钮时我如何保存内容:

创建一个私有 MOC 并将 AppDelegates managedObjectContext 分配为其父 MOC。

privateMOC = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
privateMOC.parent = managedObjectContext

privateMOC.perform 
    do 
      try self.privateMOC.save()

      self.managedObjectContext.performAndWait 
        do 
          try self.managedObjectContext.save()
         catch 
          fatalError("Failure to save context: \(error)")
        
      
     catch 
      print("Could not save \(error)")
    
  

有两个问题:

    取决于图像,当我单击“完成”按钮时,UI 被阻止,需要 3 - 5 秒后视图才会消失并显示在 TableView 中。

    我查看了实际的数据库.sqlite 发现,一个新添加的条目(UITextView 中的文本和图像)使得数据库大小几乎增加了12MB! (也许图片占用太多空间?)

对如何解决这些问题有什么建议吗? 谢谢!

【问题讨论】:

【参考方案1】:

这些问题在您的用例中很难预防。通过在包含图像的NSAttributedString 上使用NSCoding,您需要的是一个二进制 blob,您无法以任何方式控制编码过程。

可能是图像尺寸过大,例如因为您保存的是未压缩的数据,而不是 PNG 或 JPEG。但是您对此无能为力,因为您无法控制NSAttributedString 的处理方式。因此,您可能会被大数据量所困扰。 较长的处理时间可能与前一点有关——您无法控制NSAttributedString 在内部执行的操作,但很可能大部分时间都用于处理图像。

如果您自己编码属性字符串而不是使用可转换属性,您可能会缩短保存时间。然后您可以在后台提前开始编码,而不是在保存数据时进行。您可能无法修复编码时间,但您可以让它更早发生并且不那么引人注目。不过,我认为只要您使用编码的属性字符串,您就会被大小所困扰。

我不知道您的应用在做什么,但如果您可以摆脱潜在的大量 NSAttributedStrings,您将避免遇到的问题。

【讨论】:

非常感谢您的详细解释!你说的对!图像的大小很大(~13MB),没有任何压缩。我试图保存原始图像。原始图像宽度:2448.0 原始图像高度:3264.0 原始图像大小(以字节为单位):13532006(~**13MB**!)压缩后图像宽度:可选(750.0)压缩后图像高度:可选(1000.0)压缩后图像大小(以字节为单位) :908975 (~900kb) 压缩后速度快很多。但是,它在保存上下文时仍会阻止 UI。如何在不阻塞我的 UI 的情况下将其保存在后台? 我在想,使用二进制核心数据属性而不是可转换属性,您必须自己调用 NSCoding 方法。您可以在尝试保存更改之前在后台队列中执行此操作。您可能会使用NSKeyedArchiver 进行编码,使用NSKeyedUnarchiver 进行解码。 谢谢!问题是内容设置为可转换的,我没有将其更改为二进制的选项。因为否则我将不得不进行数据库迁移以将所有以前的内容转换为二进制(我之前做过迁移,这很痛苦,许多用户甚至丢失了他们的数据:()。 我可能来不及回答这个问题,但我遇到了类似的问题,当我尝试保存 managedContext 时,我的 UI 被阻止了 3 到 5 秒。问题是我试图保存在 performAndWait() 块中。我将其更改为 perform() 块,它工作正常。如果你不需要 performAndWait() 那么你可以尝试改变它。

以上是关于在 NSAttributedString 中添加图像并保存到 Core Data 性能的主要内容,如果未能解决你的问题,请参考以下文章

如何将 HTML 的 CSS 添加到 NSAttributedString?

使用 Swift 在 iOS 11 中为 NSAttributedString 添加删除线

如何将函数调用(不是超链接)添加到 UILabel 中的 NSAttributedString 的一部分?

在 iOS 中使用大小类缩放 NSAttributedString

在 Swift 中,NSAttributedString 的字符比字符串多?

如何为 NSAttributedString 设置动画?