【问题标题】:Should I use NSFileWrappers in UIManagedDocument?我应该在 UIManagedDocument 中使用 NSFileWrappers 吗?
【发布时间】:2012-03-18 12:39:02
【问题描述】:

我正在尝试将一个 plist 和几个二进制文件(比如说图像)存储为 UIManagedDocument 的一部分。二进制文件的名称是Core Data中的一个属性,我不需要枚举它们,只需在显示相关实体时访问正确的。

我想要的文件结构是:

 - <File yyyyMMdd-HHmmss>.extdoc
   - StoreContent
     - persistentStore
   - AdditionalContent
     - ListStatus.plist (used to store per document defaults)
       - Images
         - uuid1.png
         - uuid2.png
         - ...
         - uuidn.png

到目前为止,我已成功按照How do I save additional content into my UIManagedDocument file packages? 中的说明进行操作,但是当我尝试添加二进制文件时,有些事情我不知道该怎么做。

  1. 我是否应该将 URL /the/path/File yyyyMMdd-HHmmss.extdoc/AdditionalContent(readAdditionalContentFromURL:error: 提供的默认 URL)作为 NSFileWrapper 处理?与仅使用 URL 相比,有什么优点/缺点吗?我发现使用文件包装器更复杂,因为必须使用文件包装器访问器和 NSCoder(我猜)和文件来读取 plist,我必须存储图像目录的文件包装器,然后获取相应的带有 objectForKey 的节点(我假设)。但是 Apple 的基于文档的 iOS 应用程序编程指南关于自定义格式而不是 NSData 或 NSFileWrapper 指出“请记住,您的代码必须复制 UIDocument 为您所做的工作,因此您必须处理更大的复杂性和出错的可能性更大。”我误解了吗?
  2. 每个文档的默认值被声明为属性:setter 修改映射 plist 的 NSDictionary 并将文档标记为已更新,getter 使用正确的键访问字典。我如何公开读取/写入二进制文件的能力?我应该向 UIManagedDocument 的子类添加方法吗? - (void)writeImage:(NSString*)uuid;和 -(UIImage *)readImage:(NSString *)uuid; 我是否应该将这些数据保存在内存中,直到文档被保存?怎么样?
  3. 假设 NSFileWrapper 是可行的方法,如果我打算将此文档与 iCloud 一起使用 我应该将文件协调器与文件包装器一起使用吗?如果有,怎么做?

我们将不胜感激每个问题的任何源代码。谢谢。

P.S.:我知道我可以在 Core Data 中保存一些二进制数据,但我对这种解决方案感到不舒服。除其他原因外,如果我想创建桌面应用程序,我宁愿将 PNG 数据存储为 UIImage 的序列化版本与 NSImage 不兼容的图像文件。

【问题讨论】:

    标签: core-data icloud uimanageddocument nsfilewrapper


    【解决方案1】:

    另一个想法。您可能需要使用 NSFileCoordinator 进行读取和写入操作。从技术上讲,iCloud 容器中的任何读取或写入操作都需要使用文件协调器(与 iCloud 同步服务协调 - 这可以防止在另一个进程正在写入文件时通过读取文件意外损坏文件)。

    我知道 UIDocument 自动包装了它的大部分输入和输出方法。我猜这些方法是类似包装的(因为它们为您提供了要使用的 URL)——但是,文档不是很清楚。

    【讨论】:

    • 再次重读文档后,UIDocument 会执行“与云服务自动集成的文档文件的协调读写”。但是对于作为 writeContents:andAttributes:safelyToURL:forSaveOperation:error: 的一部分调用的 writeAdditionalContent:toURL:originalContentsURL:error: 它声明“文档数据的读取和写入 [...] 必须与其他读取并写入同一个文档文件。”正如你所说,完全不清楚。有没有办法测试是否需要?
    【解决方案2】:

    我想说的是,总的来说,我更喜欢 UIManagedDocument。与原始核心数据相比,它有一些优势。例如,它会自动为您设置整个核心数据堆栈。它还为您设置嵌套的托管对象上下文,因此您可以获得免费的后台保存。这些都不是特别惊天动地的,但它是通过少量代码实现的大量功能。

    我还没有尝试保存其他信息...但这是我的想法。

    首先,您不需要将新 URL 视为文件包装器。您应该能够对提供的 URL 执行常规文件操作。只需确保在 additionalContentForURL:error:、writeAdditionalContent:toURL:originalContentsURL:error: 和 readAdditionalContentFromURL:error: 中正确实现了所有内容。读写操作需要对称。您可能应该在 additionalContentsForURL:error: 中对数据进行快照,以便将所有内容保存在已知的良好状态(因为保存操作是异步的)。

    作为替代方案,您是否考虑过在数据模型中使用 Store in External Record File 标志而不是手动保存?这应该强制 Core Data(取决于二进制数据的大小)自动将它们存储在外部。我查看了发行说明,并没有看到任何内容说您不能在 iCloud 中使用此功能。这可能是最简单的解决方法。

    【讨论】:

      【解决方案3】:

      暂时攻击一个支点(因为我对UIManagedDocument没有任何好的经验)。

      您可以使用外部文件引用将二进制文件保存在 iOS 5.0+ 应用程序的 Core Data 中。然后您可以直接将图像的 PNG 保存到 Core Data 中,而无需担心UIManagedDocument 或膨胀的 sqlite 文件。

      没有什么能阻止您存储 PNG 而不是 UIImage。

      【讨论】:

      • 谢谢。这会将内容放在 UIManagedDocument 内的 PNG 内吗?
      • 如果您使用了UIManagedDocument,那么可以。但是,您也可以尝试不使用 UIManagedDocument,看看会发生什么。除了最不寻常的情况外,我仍然很怀疑是否需要 UIManagedDocument
      • 能够使用 iCloud 与不使用同一 iCloud 帐户的其他用户共享文档是我的动力。
      • 我很好奇你将如何做到这一点。使用直接的 Core Data 实现,您可以与 iCloud 同步,所以我很好奇您在 UIManagedDocument 中使用的不同之处。
      • 为了与另一个用户共享一个文档,并让另一个用户拥有两个文档,Core Data + iCloud 的方案是行不通的。计划是通过 URLForPublishingUbiquitousItemAtURL:expirationDate:error: 共享 url,但这需要封装在 UIDocument(子类)包装器中。
      猜你喜欢
      • 1970-01-01
      • 2021-02-07
      • 2011-03-19
      • 2016-04-12
      • 2014-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多