http://media.cocoachina.com/local-file-storage-in-ios-5/

 

文/ Nick (iphoneincubator)

关于iOS 5的本地文件储存Marco(Instapaper 的开发者)写过一篇很好的帖子阐述过相关问题,有兴趣的同学可以先阅读下他的文章然后再看下文。

在苹果开发者的论坛上也有许多相关问题的讨论贴:

安全地保存文件?

如何在缓存文件夹内持久保存文件?

如果我想让文件永久保存且不会和iTunes同步,我该把文件保存在哪里?

iCloud 的云备份占用了巨大的空间?

 

几点困惑

在苹果开发者论坛的讨论中,总结出以下几点令人困惑的问题:

  1. 关于缓存和临时文件目录的含义
  2. 苹果开发文档的更新修改
  3. 应用审核被拒
  4. iTunes和iCloud会备份哪些文件
  5. iOS 5的机制改变

下面让我们逐个讨论:

 

关于缓存和临时文件目录的含义

如果你有OS X或者Unix的开发背景,就会很容易明白苹果的立场:即无法保证数据在这两个目录中能持续地保存多久。

实际上在应用沙盒(sandbox)里的临时文件目录(tmp directory)和根目录下临时文件目录(root /tmp)不太相同,但也不需要区别对待这些目录。

过去如果你从没观察到文件在这些目录里被删除,那并不保证以后不会。特别是当这个改变和开发文档说明一致时,这是一个普遍的规律。

 

苹果开发文档的更新修改

直到2011年6月的官方开发文档中关于 <Application_Home>/Documents 的说法是:

“使用这个目录来存储用户文档和应用数据文件”

这个用法相当明确。而iOS 5改变了Documents 目录用法却不给出任何合适的替代方法,因此难怪开发者感到不高兴。

而关于 <Application_Home>/Library/Caches 的说法是:

“使用这个目录来写入任意应用的专属支持文件,以便你可以使它们在应用程序启动时或者在应用程序更新时保持不变。

你的应用程序通常要负责这些文件的添加和删除,有些情况下也要能够重新创建所需文件,因为iTunes会在恢复模式下删除保存在这里的文件。”

这段话的涵义很不明确。我读完觉得大意是苹果在iOS 5上做了个根本上的改变,而使得看这段说明很矛盾。但是如果你仔细看字眼“通常要”(”generally”)和“能重新创建”(”able to re-create”)的话,在苹果警告你的应用内文件不合规范时,你就会明白那些地方需要改进了。

关于iOS 数据存储指导手册(iOS Data Storage Guidelines)的说明:

“为了尽力确保文件备份高效,请务必根据以下的指导来保存你的应用数据:

1、只有那些用户生成的文档和其他数据或者是那些不能被你的应用所重建的数据应当保存在<Application_Home>/Documents 目录内。这些数据文件将会自动的通过iCloud备份。

2、那些可以重新下载或者重新创建的数据应当保存在<Application_Home>/Library/Caches 目录内。你可以把数据库缓存文件或者可下载的内容如杂志、报纸、地图应用的数据等放入缓存目录里(Caches directory)

3、临时需要的数据应该保存在<Application_Home>/tmp 目录内。尽管这些文件不会备份到iCloud里,请记住在你不再需要它们时立即删除掉这些文件,这样它们就不会继续浪费用户设备的储存空间了。”

事实上许多报纸、杂志和地图的应用单纯的目的就是想离线显示内容,如果我们暂时无视这点,那么以上的指导讲的很清楚,可以去参考。

 

应用审核被拒

开发者目前报告说那些在Document 目录内保存任意/少量/大量数据的应用正在审核中被拒。

应用审核部门不太可能面面俱到,比如理清楚哪些文件该储存到哪些目录内、哪些文件是用户生成的、哪些数据是可以重新下载或重新被创建的。有些开发者报告中说,他们跟应用审核部门解释清楚应用是如何保存数据、如何遵守指导原则的,之后他们的应用也得到了通过。

 

iTunes和iCloud会备份哪些文件

应用里home 目录内的所有数据都会被备份除了:

  1. 编译后的应用包文件 (.app)
  2. <Application_Home>/tmp 目录内的文件
  3. <Application_Home>/Library/Caches 目录内的文件

这些在iOS数据储存指导手册上(iOS Data Storage Guidelines)和Michael Jurewitz的评论里已讲的很清楚了。

其他开发文档里也明确的指出Application Support 目录内的文件也会被iTunes备份(假设iCloud也会)。在讨论中有些开发者认为Application Support 目录内保存文件相比Caches 目录更安全点(更加持久)。我觉得应用审核部门会拒掉那些在Application Support 目录内保存大量数据的应用,这和Document 目录内的严格审核是一样的,都是拜iCloud的储存空间不足所赐。

 

还有些什么值得注意的?

再也没有一个目录可以让你的应用保存文件于其中并可以:

  1. 不被iTunes或者iCloud备份
  2. 不会因空间受限而被清除

很明显在iOS 5.0上想做到这些已经迟了。但是如果足够多的开发者据理力争,让苹果知道他们非常需要在自己的应用内保持这个功能,或许下个版本会加入进来。提示:提交文件bug 报告。

 

开发者要做些什么?

如果你当前正在Documents 目录内保存文件的话

你的应用当然可以继续在iOS 5内正常工作,你的用户可能会抱怨有大量的数据被备份到了iCloud上。(详见以下内容)

然而当你更新你的应用时,可能会因为在Documents目录内保存太多数据而被拒绝通过审核。

如果你正在或者考虑到在Caches 目录内保存文件的话

请确保在Caches 目录内你保存的文件忽然消失的情况下,你的应用依然可以处理妥当。一种处理的方法是,把保存在Caches目录内的所有文件的源URL(原始路径或地址)列入进一个清单里。这样应用通过遍历清单就可以验证文件是否依然存在了。

如果有任何文件消失了你可以显示对话框向用户致歉,解释清原因并询问是否要重新下载文件。假如设备是离线的,你只能对用户致歉然后告诉用户“你完了”。

还有许多比这两种更复杂的情况,例如:分装的数据哪些还能使用。你需要决定显示哪些数据,显示多少等。

一名开发者在苹果论坛上讲的用户使用案例,我觉得很有趣:他的应用是为飞行员显示地图 的。如果他把可以重新下载的地图放到Caches 目录内,那么如果地图数据被iOS 5突然删掉,这时飞机还在天上,可能就悲剧了。让飞行员重新下载地图数据的对话框绝对会深深地伤害到他的感情。

迁移已存在的数据

如果你服从 iOS 5或iCloud的新规则去更新应用并把文件储存到Caches 目录内的话,那么你可能需要把已存放在Document 内的文件转移到 Caches 内。我确信应用审核部分不会去测试这个,因为他们没有你存有数据的老版本应用。但是这样做很对。

记住不要在应用程序启动时的主线程中消耗太多的资源来进行文件转移。这样会使你的应用被启动时间监视程序Kill掉。

提前警告

当应用在运行时,如果设备正处于空间不足的情况下,你可以告知用户。虽然这样不能阻止文件被删掉,但至少可以让用户认识到这个问题的存在。

我不清楚在iOS 5的清除程序运行前,磁盘空间的最低值是多少,并且我也怀疑苹果会给出具体细节。如果你有任何自己试验出的结果请务必在下面添加评论指出。

让苹果意识到这是个很大的问题

提交文件bug 报告(File a bug report)。

 

用户能做什么?

一直到现在,那些保存许多数据在目录内的应用对于备份来说很头疼,因为iTunes备份它们要花很长的时间。当有许多的文件必须备份时,这种情况尤其恼人。

通过iCloud备份的话,用户们可能不想占用他们那可怜的5GB储存空间(或是花钱购买额外空间)来备份那些他们认为不重要的数据。单个的应用可 以关掉iCloud备份。在应用设置中能很容易的找到设置:iCloud > 储存与备份>管理储存空间>备份。在备份选项列表里每一个应用都可以选择是否备份。可能你的用户不太容易能找出设置,你可能需要发邮件去指导 他们。

这些是我的理解,尽管我还没来得及测试关掉iCloud备份对iTunes的备份是否有影响。但是对于那些再也不用数据线连接电脑来同步的用户,按上述说明关掉iCloud备份的应用是没有备份数据的。