管理iOS应用中的Documents / Inbox文件夹的好方法

时间:2013-03-29 17:01:40

标签: ios

当文档交互系统将文件传递到iOS应用程序时,该文件的副本将存储在应用程序包的Documents/Inbox文件夹中。在应用程序处理完文件后,显然需要从Documents/Inbox中删除该文件,否则该文件夹将继续增长并浪费存储在设备上。

我对这个简单的解决方案(A)感到不舒服,因为我的应用程序需要在完成处理和删除文件之前与用户进行交互。如果用户在此交互期间暂停应用程序,并且该应用程序在后台处理时会被杀死,则应用程序下次启动时将不会删除过时文件。当然,我可以改进我的应用程序以涵盖这种情况,但我怀疑总会有另一个边框案例会让我留下一个“不干净的”Documents/Inbox文件夹。

因此,优选的解决方案(B)将是在适当的时间移除Documents/Inbox文件夹(例如,当应用程序正常启动时,即不通过文档交互)。我仍然对此感到不舒服,因为我将访问一个文件系统路径,其位置未在任何地方正式记录。例如,如果在未来版本的iOS中,文档交互系统不再将文件放在Document/Inbox中,我的应用程序就会中断。

所以我的问题是:

  1. 您会推荐解决方案A还是B?
  2. 您是否使用了不同的方法,可以概述一下您的应用管理方式Document/Inbox吗?
  3. 最后但同样重要的是:您是否知道一篇涵盖该主题并且我忽略了的官方Apple文档?

3 个答案:

答案 0 :(得分:13)

由于我提出了这个问题,我已经实施了以下解决方案:

  • 我重新设计了我的应用程序,以便它立即处理通过文档交互传递给它的文件,而根本不涉及用户。除非应用程序在处理文件时崩溃,或被暂停和终止,否则应该始终保持干净Documents/Inbox
  • 为了涵盖崩溃或暂停/终止的(罕见)情况,我的应用程序在正常启动时删除了Documents/Inbox文件夹(即没有文档交互的目的)。为实现此目的,Documents/Inbox文件夹路径必须是硬编码的。

以下是解决方案的想法:

  • 重新设计应用
    • 最初,为用户提供一个如何处理文件的选择似乎是一个好主意 - 毕竟,提供选择会使应用程序更加灵活,并为用户提供更多自由,对吗?
    • 然后我意识到我正在努力转移决定如何处理文档交互的责任。所以我咬紧牙关,事先做出了艰难的决定,然后愉快地在我的应用程序中实现了一个简单直接的文档交互系统。
    • 事实证明,没有用户互动也意味着该应用程序更易于使用,因此这对我作为开发人员和我的应用程序的用户来说都是双赢的局面。
  • 在应用启动期间删除Documents/Inbox文件夹
    • 在应用启动期间删除Documents/Inbox文件夹只是事后的想法,而不是我的应用处理文档互动的必要部分
    • 因此,我非常愿意承担Apple可能在将来某个时候更改收件箱文件夹的文件系统路径的风险。可能发生的最糟糕的事情是我的应用程序将开始累积一些文件,这些文件是崩溃或暂停/终止方案中的残留物。

最后,还有一些进一步发展的想法:

  • 如果事实证明确实应该是应用程序处理文档交互的方式不止一种,我会添加用户首选项,以便用户必须事先做出决定,并且应用程序无需停止其处理以要求用户进行选择。
  • 如果在文档交互处理过程中发现用户交互是绝对不可避免的,我会看一下这种方法:1)在允许用户进行交互之前,从Documents/Inbox移动文件到某种“staging”文件夹; 2)让用户进行互动; 3)以“用户选择的任何方式”处理“staging”文件夹中的文件。这里重要的是“staging”文件夹是在一个已知的位置,完全由应用程序管理。如果用户在用户交互步骤中暂停然后终止应用程序,则可以在下次启动应用程序时采取适当的操作。

修改

在iOS 7中,一旦创建Documents/Inbox,就无法再删除它。 NSFileManager方法removeItemAtPath:error:返回Cocoa错误513,该错误解析为NSFileWriteNoPermissionError(参见this list of Foundation constants)。该错误似乎与POSIX权限无关,但是,它看起来好像系统本身会干扰删除尝试(可能保护应用程序包结构?)。

同样值得注意的是,Apple现在在Documents/Inbox方法UIApplicationDelegate的文档中明确指出application:openURL:sourceApplication:annotation:。他们也说

  

[...]您的应用有权读取和删除此目录中的文件,但无权写入这些文件。如果要修改文件,则必须先将其移动到其他目录。

the docs中有关于文件可能加密的更多内容,但您应该自己阅读。

答案 1 :(得分:1)

通过引入“文件”应用程序和“就地打开”功能,此问题变得更加复杂。

如果您在info.plist中未启用“ 不支持打开文档”,则情况几乎相同,并且仍然会显示从其他任何应用程序打开的文件在Documents/Inbox目录中。但是从“文件”应用打开的文件显示在另一个收件箱中,当前位于tmp/<bundle ID of app>-inbox。仍然建议您在完成处理后删除该文件,但是偶尔清理目录的需求就更少了,因为tmp目录有时会被iOS清理一次。

如果这样做已打开“支持在适当位置打开文档”,那么情况将发生巨大变化。从“文件”应用程序和某些其他应用程序打开的文件不再复制到收件箱中,而是在原始位置传递给您。通常是在“文件”应用程序本身内部,在“文件”应用程序引用的另一个应用程序中的某个位置,甚至是一些常规iCloud位置。如果您将文档文件夹中的文件公开,则它甚至可能是您自己应用程序的文件之一。

不用说,如果您得到这样的文件,则一定不能删除它。但是,如果该文件位于收件箱中,而且还会经常发生,那么您必须将其删除。为了确定这一点,application:openURL:options:调用的选项包含一个UIApplicationOpenURLOptionsOpenInPlaceKey键。如果该值的值为(NSNumber否,则该文件位于收件箱中,应将其删除。它的值为YES,然后就地打开它,并且不能删除它。

请注意,对于已打开的文件,还需要获得使用它们的权限。您可以这样做,但是要通过startAccessingSecurityScopedResourcestopAccessingSecurityScopedResource调用来访问文件。有关详细信息,请参见Apple documentation

答案 2 :(得分:0)

我刚才面临同样的问题。和你一样,我没有一个好的解决方案,但是为了回答你的问题,我倾向于选项A而不是选项B,因为我不喜欢可能在操作系统的未来版本中出现问题的想法。因为,在我的情况下,一旦我显示文档的预览就没有用户交互,我可以在收到–documentInteractionControllerDidEndPreview:委托回调时继续删除它。这是理论上的,因为我还没有对此进行编码,并且暂时不会这样做,因为它是一个低优先级的项目。如果它不起作用或有其他问题,我会在这里报告。我为了查找Apple的文档而输入的Google搜索指向了这个StackOverflow帖子。我还没有看到Apple或其他任何有关此主题的其他有用信息。