iCloud官方文档

官方地址:
iOS App Programming Guide -> iCloud Storage

这个偏理论一些,提供了很多iCloud应用设计层面的东西,大家感兴趣,可以一看。


如果需要iCloud上手教程,可以参考我的另外一个贴子:http://www.cocoachina.com/bbs/read.php?tid=86246
-----------------------------------------------------------------------------------------------------------------------------




iCloud支持两种应用存储:

  • document storage:存储用户文档和应用数据到用户的iCloud账户
  • key-value data storage:分享小量的非关键配置数据到应用的多个实例


iCloud App的设计考虑
首 先需要确认的是采用document storage还是key-value data storage。document storage用于存储应用数据,要么是应用创建并私有管理的数据,要么是用户创建的数据。所有用户面对的数据都应该是document storage,例如用户创建的文档。key-value data storage主要用于非关键的配置数据,你希望在多个app实例中共享,例如应用使用的参数和配置信息(典型的例子如Newsstand应用中用户上一次阅读的刊物和阅读位置)。

document storage 和 key-value data storage的区别:

属性Document StorageKey-Value storage
管理的数据类型?文件和目录只能是Property-list数据
什么时候应该使用?使用Document Storage来管理应用的关键数据。与应用main data model直接相关的文件和数据,总是应该使用Document Storage。如用户文档、私有的app数据文件、以及应用或用户生成的数据文件参数或其它配置数据,如果需要在多个app实例之间共享,并且不是关键数据,就可以使用key-vlaue storage。只能存储property list数据,并且容量有限。
是否需要file presenter和file coordinator
怎样定位数据?使用 NSMetadataQuery 对象来查找文件使用默认的 NSUbiquitousKeyValueStore 对象来获取已知key对应的值
如何管理数据?使用NSFileManager类来管理文件和目录。使用标准文件系统函数来打开、关闭、读取和写入文件使用默认的NSUbiquitousKeyValueStore 对象来获取和设置key和value
能存储多少数据?只受用户iCloud账户的空间限制限制为64KB(单个key也限制为64KB)
怎样处理冲突?应用的 file presenters 必须手工解决冲突最后设置的值总是当前值。设备提供的时间戳用于确定最新的值
要求设置哪个entitlement?com.apple.developer.ubiquity-container-identifierscom.apple.developer.ubiquity-kvstore-identifier
数据什么时候同步?设备端发生变化时,iCloud总是会拉取文件元数据和数据;设备总是会拉取文件元数据,但是直到应用试图使用文件时才会拉取文件数据定期在设备和iCloud之间传输key-value数据
怎样在运行时检查iCloud可用?对某个你已经注册的容器目录调用 URLForUbiquityContainerIdentifier: 方法,如果方法返回nil,表示document storage不可用调用 NSUbiquitousKeyValueStore 的 synchronize 方法,如果返回YES,iCloud可用,并且有修改同步到本地用户默认数据库;如果返回NO,iCloud要么不可用,要么没有变化需要同步。无论如何,都可以直接使用本地的用户默认数据库。
系统提供了什么用户界面支持?没有,应用负责提供支持iCloud的信息和界面。没有,多数情况下,你不应该让用户知道key-value数据存储在本地还是iCloud中。




另一个设计考虑是应用的用户界面如何整合iCloud支持。特别是文档,有时候你需要提醒用户文档的状态,比如是否已经下载、版本冲突需要解决等。一般都需要在界面上增加一些不引人注目的元素,以在适当的时候提示用户。



配置应用的iCloud Entitlements
使用iCloud的应用必须以iCloud特定的Entitlements签名。这些entitlements为应用提供一层安全性,确保只有你的应用才能访问自己创建的文档。系统也依赖于你提供的Entitlement值来区分用户iCloud账户中你的应用与其它应用的文档。

Xcode中启用iCloud Entitlements:

  1. 选择应用的target
  2. 选择Summary
  3. 在Entitlements中,勾选"Enable Entitlements"

当 你启用App target的Entitlements时,Xcode自动为你的应用配置了document storage和key-value data storage。每个Entitlement包含一个key,是一个或多个容器标识字符串。容器标识字符串标识了iCloud中的一个容器目录,你用来存储应用的文件。

Xcode按以下方式来配置Entitlements:

  • iCloud容器域标识了应用在用户iCloud存 储中能够访问的容器目录(这个域对应于com.apple.developer.ubiquity-container-identifiers)。你添 加到这个列表的字符串必须匹配你的团队创建的应用bundle ID。Xcode使用当前app的bundle ID来指定第一个字符串,如果你希望多个app共享一个main容器目录,你可以修改为不同的bundle ID。你还可以为团队的其它应用添加额外的bundle ID(第一个字符串必须不包含任何通配符,随后的字符串则可以包含通配符)
  • iCloud的key-value存储域包含应用存储到iCloud的key-value data storage的单个容器标识字符串(对应于 com.apple.developer.ubiquity-kvstore-identifier)

你 在Xcode中设置的bundle ID并不是完整限定的容器标识字符串。完整限定的容器标识的格式 是: <TEAM_ID>.<BUNDLE_IDENTIFIER>,其中<TEAM_ID>是10个字符的团队标 识;<BUNDLE_IDENTIFIER> 则是iCloud容器域中的某个bundle ID。当在代码中获取某个容器目录的URL时,你需要传递完整限定的字符串给 URLForUbiquityContainerIdentifier: 方法。不过你也可以传递nil,来获取列表中的第一个容器目录的URL

通过在Entitlements中指定多个容器标识,使用iCloud document storage的应用可以读取和写入内容到多个容器目录。iCloud容器域允许你指定多个字符串。第一个字符串是应用的main容器标识,任何额外的字符串则代表你其它应用的容器标识。查找时会返回所有可用容器目录中的所有文件。



使用iCloud Document Storage
iCloud Document Storage让你将文件和目录移动到用户的iCloud账户,并在那里管理这些文件。在某个设备上修改文件或目录,会先存储在本地,然后再通过本地daemon进程push到iCloud。文件传输对应用是透明的,因此应用只需直接操作文件。


设计应用使用iCloud Document Storage,需要一些重大的应用修改,主要包括:

  • 应用执行的早期,调用 URLForUbiquityContainerIdentifier: 方法检查iCloud是否启用。扩展应用Sandbox来包含应用请求的每个容器目录,也需要调用这个方法。
  • 显式地整合 file presenters(如UIDocument类)到应用的数据层
  • 显式地移动文件到iCloud
  • 准备好处理版本冲突
  • 使用查找来定位iCloud中的文件
  • 处理文件在iCloud中,但是没有完全下载到本地设备的情况;可能需要向用户提供及时的反馈
  • 如果要在iCloud中存储live database,使用Core Data,不要使用SQLite
  • 如果应用还有Mac OS X版本,为所有应用使用通用文档格式

App支持iCloud的大部分工作都在数据层。与iCloud的交互也主要是应用要存储使用的文件和目录。不过底层数据变化时,用户界面也需要一定的修改,以通知用户相关的状态。当然,应用应该尽可能地让用户无需关心本地还是iCloud存储。

检查iCloud Document Storage是否可用
每个Apple ID用户都有一个免费的iCloud账户,但是用户可能禁用某个设备的iCloud。因此使用iCloud接口之前,必须先调用 URLForUbiquityContainerIdentifier: 方法检确定iCloud是否可用。返回nil表示不可用,返回URL表示可用

第一次对指定的容器目录调用 URLForUbiquityContainerIdentifier: 方法,iOS会扩展应用Sandbox来包含该容器目录。因此需要至少成功调用一次该方法,以确保iCloud可用,main容器目录也可以访问。

整合 File Presenters 到应用
iCloud中存储的所有文件和目录都由file presenter对象管理;你对这些文件和目录的修改都必须通过一个file coordinator对象。

file presenter实现了 NSFilePresenter 协议,主要的职责是作为特定文件或目录的响应代理。在外部源能够修改一个文件之前,注册的file presenter会得到通知,并有机会执行任何必要的簿记(bookkeeping)工作。

当应用想要修改一个文件时,它必须通过一个 NSFileCoordinator 对象来执行修改,本质上会锁住文件。file coordinator 阻止外部源修改文件,并且递送相关的通知给其它 file presenters。

整 合 file presenter 到应用最简单的方法是使用 UIDocument 类。这个类实现了 NSFilePresenter 协议,并为你处理了所有文件相关的管理。应用唯一需要做的事情,就是在得到通知时,读取和写入文档数据。不管是用户生成内容的文件(因此直接显示给用户),还是应用替用户创建的文件(无需用户交互),都可以使用UIDocument。

操作iCloud中的文件和目录
iCloud文件和目录和本地文件目录一样,应用使用相同的技术来管理文件和目录。你可以打开、创建、移动、复制、读取、写入、删除、以及其它操作。本地文件目录和iCloud文件目录的唯一区别是访问的URL不同。本地文件目录的URL相对于应用Sandbox,而iCloud文件目录的URL则相对于相应的iCloud容器目录。

要移动一个文件或目录到iCloud

  1. 在应用Sandbox中创建本地文件或目录。使用的时候,必须由file presenter来管理文件或目录。如UIDocument
  2. 使用  URLForUbiquityContainerIdentifier: 方法获取iCloud容器目录的URL
  3. 使用容器目录URL来构建一个新的URL,指定文件或目录在iCloud中的存储位置
  4. 调用 NSFileManager 的 setUbiquitous:itemAtURL:destinationURL:error: 方法移动文件或目录到iCloud绝对不要在应用的主线程中调用这个方法,否则可能会长时间阻塞主线程,或者与应用所拥有的file presenter产生死锁。

移动一个文件或目录到iCloud时,系统从应用Sandbox中复制该item到private本地存储,这样才能被iCloud daemon监测到。尽管文件此时已经不在应用Sandbox中,应用仍然对其拥有完全访问。虽然文件仍然有一份拷贝保留在当前设备的本地,文件同时还发送到了iCloud,这样就能分布到其它设备去。iCloud daemon处理了所有工作,确保本地拷贝与iCloud是相同的。因此从应用的角度来说,文件就是在iCloud中。

你对iCloud中的文件和目录的所有修改都需要使用一个 file coordinator 对象。包括移动、删除、复制、重命名等操作。file coordinator确保iCloud daemon不会同时修改文件或目录,并确保你修改时能够及时地通知其它人。

命名文件和目录时,尽量使用字母数字,避免使用特殊标点和其它特殊字符。同时你还应该假设文件名是大小写不敏感的(因为iCloud支持Windows)。最后尽量保持文件名简单,以确保这些文件能够在不同文件系统中正确地处理。

选择一种响应版本冲突的策略
iCloud文件的版本冲突不可避免,因此应用必须对冲突采取一种解决策略。当应用的两个实例同时修改一个文件并传输给iCloud时就会发生冲突。iCloud会保存所有冲突的版本,并通知应用的file presenter发生了冲突需要解决。

App应该尽快地尝试解决版本冲突,当冲突发生时,其中一个文件被指定为current file,其它所有版本都是冲突版本。当前文件和冲突版本文件都由 NSFileVersion 对象来管理,可以通过类方法来获取。

解决冲突:

  1. 使用类方法 currentVersionOfItemAtURL: 获取当前文件版本
  2. 使用类方法 unresolvedConflictVersionsOfItemAtURL: 获取所有冲突版本的数组
  3. 对每个file version对象,执行以下任何动作来解决冲突:[list=1]
  4. 如果实际可行的话,合并冲突文件修改的数据
  5. 如果能够安全地执行而不丢失数据的话,忽略某个冲突版本
  6. 提示用户选择保留哪个版本的文件(当前文件或冲突文件),这是最后的选择。

更新当前文件:

  1. 如果当前文件胜利(winner),不需要更新当前文件
  2. 如果某个冲突版本胜利(winner),使用 coordinated write 操作,以冲突版本的文件内容覆盖当前文件
  3. 如果用户选择保存冲突版本为另一个名字,以该冲突版本的内容创建一个新文件

设置所有冲突版本对象的 resolved 属性为YES。设置这个属性会导致冲突版本对象(及相应的文件)从用户的iCloud storage中删除。如果使用UIDocument类,你通过 observing 文档状态变化通知,并检查  documentState 属性来判断是否发生冲突
如果使用自定义 file presenter,每当报告有一个新版本时,你都应该检查它是否冲突版本。

整合查找(Search)到应用基础架构
和应用Sandbox不同,iCloud中的文件添加和删除,你的应用可能都不会直接知道。在这台设备上创建的文件,最终会出现在另一台设备中。如果应用不主动查找文件,那就不能及时地出现在用户界面中。因此应用需要使用 NSMetadataQuery 对象来查找iCloud容器目录中的文件或目录。

当应用在前台时,你可以保留一个 metadata query 一直运行,来接收文件添加或删除的通知;应用进入后台时,就停止这个 metadata query 查询。


只有 iCloud 启用,并且相应的容器目录已经创建时,metadata查询才会有返回结果。在运行时,确保使用 URLForUbiquityContainerIdentifier: 方法来检测iCloud已经启用,而且应用支持的容器目录也可用。这个方法在容器目录不存在时,会自动创建出来。


Metadata 查找应用entitlement中设置的所有容器目录,并返回合并后的所有结果。如果你希望只查找一个容器目录,可以使 用 URLForUbiquityContainerIdentifier: 方法来获得该容器目录的URL,然后使用 NSFileManager 类来获取目录内容的静态列表。


确定文件或目录的传输状态
你写到iCloud容器目录的item会尽可能快地自动传输到iCloud服务器。但是由于网络和设备类型的原因,文件或目录可能不会立即下载到设备或上传到服务器。如果你需要确定文件的状态,可以使用 NSURL 的 getResourceValue:forKey:error: 方法,来获取以下属性的值:

  • NSURLIsUbiquitousItemKey:表示item是否存储在iCloud
  • NSURLUbiquitousItemIsDownloadedKey:表示当前版本是否已经下载并且可访问
  • NSURLUbiquitousItemIsDownloadingKey:表示当前版本是否正在下载并且暂时不可用
  • NSURLUbiquitousItemPercentDownloadedKey:对于正在下载的item,表示已经下载的修改的百分比。可以使用这个值来更新进度条。
  • NSURLUbiquitousItemIsUploadedKey:表示本地的修改是否成功上传到iCloud服务器
  • NSURLUbiquitousItemIsUploadingKey:表示本地的修改是否正在上传到服务器
  • NSURLUbiquitousItemPercentUploadedKey:对于正在上传的item,表示当前已经上传的修改的百分比


虽然iCloud服 务器会非常努力地拉取应用在本地做的修改,但是iOS设备通常却不会主动从服务器拉取修改,除非你试图访问该文件。如果你试图打开一个正在下载的文 件,iOS会阻塞发起打开请求的线程,直到文件被完全下载并且可用。因此如果你担心潜在的延迟,就根据需要检查文件的当前状态,同时更新用户界面,提示用 户当前文件正在下载,暂时不可用。


使用尚未下载完成的文件
iCloud中的文件发生改变时,iOS设备不会自动下载这些修改数据。相反iOS设备会下载文件的元数据,因此知道此时文件已经有修改。实际修改的数据只有以下情况发生时,才会被下载:

  • 应用试图打开或访问文件
  • 应用调用 startDownloadingUbiquitousItemAtURL:error: 方法,显式地下载文件修改

如果应用打开尚未下载完成的文件,用于打开文件的 file coordinator 会阻塞你的应用,直到文件或修改被完全下载。如果文件或修改比较大,可能会导致很差的用户体验,因此试图打开一个文件之前,应该首先检查文件的下载状态。NSURL 类定义了iCloud item相关的属性,可以检查iCloud文件的状态


检查文件是否已经下载完成:
- (BOOL)downloadFileIfNotAvailable:(NSURL*)file {
   NSNumber*  isIniCloud = nil;

   if ([file getResourceValue:&isIniCloud forKey:NSURLIsUbiquitousItemKey error:nil]) {
      // If the item is in iCloud, see if it is downloaded.
      if ([isIniCloud boolValue]) {
         NSNumber*  isDownloaded = nil;
         if ([file getResourceValue:&isDownloaded forKey:NSURLUbiquitousItemIsDownloadedKey error:nil]) {
            if ([isDownloaded boolValue])
               return YES;

            // Download the file.
            NSFileManager*  fm = [NSFileManager defaultManager];
            [fm startDownloadingUbiquitousItemAtURL:file error:nil];
            return NO;
         }
      }
   }

    // Return YES as long as an explicit download was not started.
    return YES;
}


iCloud调整用户界面
所有为了iCloud所做的用户界面调整,都应该尽量不引人注意。当iCloud不可用时,你存储在iCloud中的文档和你存储在本地是完全一样的。唯一的区别是文件系统中的位置。因此大部分用户界面都应该保持一致。


以下情况可能需要针对iCloud修改用户界面:

  • 当用户生成的文档在使用之前必须被下载。只有你提供了文档浏览器,才需要让用户来控制是否下载文档。应用使用的私有文件,应该在不可用时自动去服务器下载。你用来提示用户的信息应该尽量友好,并提供用户“开始文档下载”的选项。如果下载时间可能超过几秒钟,你需要显示一个当前下载进度。
  • 当出现必须由用户解决的版本冲突。如果应用需要用户协助,才能解决冲突,就应该友好地提示冲突信息,但千万不要显示警告,或其它任何破坏性的界面。
  • 当你希望提供用户选项,为应用启用或禁用iCloud。如果应用包含一个Settings Bundle或者内部的参数设置,你可以提供一个参数,让用户选择是否使用iCloud



iCloud结合Database使用
只有应用使用Core Data来管理数据库时,才能将SQLite数据库整合到iCloud。不支持使用SQLite接口访问iCloud中的live数据库,这样做很可能会毁坏你的数据库。


但是只要你遵守一些额外的步骤,来设置Core Data结构,你就可以创建基于SQLite的Core Data,从而启用iCloud支持。当然,其它类型的Core Data Store(不基于SQLite),则无需修改可以直接支持iCloud


使用Core Data和SQLite store时,实际的数据库文件不会传输到iCloud服务器。相反,每个设备都维护自己的SQLite store拷贝,并通过将修改写入到日志文件来同步它的内容。设备与iCloud之间真正传输的是log file,在每个设备中,Core Data拿到log file的内容,然后使用这些内容来更新本地数据库。当然最终的效果就是每个本地数据库都拥有完全相同的修改。


设置Core Data store来处理iCloud,只需要你执行很少的额外工作。但是具体的步骤取决于你使用Core Data store作为中央库(Central Library),还是为单个文档分别创建独立的Core Data Store。


使用Core Data管理文档
应 用管理Core Data store为单独的文档时,可使用 UIManagedDocument 对象来管理单个文档。UIManagedDocument 类自动在应用bundle中查找所有managed object model,并使用它们作为文档数据的基础(你也可以覆盖 managedObjectModel 属性自定义指定子类的object models)。由于大部分数据由managed object context处理,意味着你通常可以直接使用 UIManagedDocument 类而不需要继承子类。UIDocumemnt的自动保存行为,能够自动处理所有文档的保存工作。


创建新文档时,执行以下步骤:

  1. 创建 UIManagedDocument 对象
  2. 文档的 persistentStoreOptions 属性是一个Dictionary,添加一个 NSPersistentStoreUbiquitousContentNameKey 键,值为你标识该文档的唯一名字。
  3. 添加一些初始化数据到文档
  4. 使用 saveToURL:forSaveOperation:completionHandler: 方法将文档保存到磁盘。保存文档时,你也可以直接将它保存到iCloud;或者先保存在本地目录,然后再移动到iCloud。保存到iCloud需使用 URLForUbiquityContainerIdentifier: 方法获得相对iCloud的URL;如果已经保存到本地,则可以使用 setUbiquitous:itemAtURL:destinationURL:error: 方法将其移到iCloud

当 你创建一个新文档时,Core Data创建一个file package,包含文档的内容。这些内容有一个 DocumentMetadata.plist 文件,以及一个包含SQLite data store的目录。除了SQLite data store(保留在本地),file package中的任何东西都会被传输到iCloud服务器。


打开iCloud中的现有文档时,执行以下步骤:

  1. 使用 NSMetadataQuery 查找iCloud中的文档,Metadata查找会标识你iCloud中的所有Core Data文档。如果文档是其它设备创建,文档file package最初只有 DocumentMetadata.plist 一个文件。
  2. 打开 DocumentMetadata.plist 文件,并获取 NSPersistentStoreUbiquitousContentNameKey 键的值
  3. 创建 UIManagedDocument 对象
  4. 添加 NSPersistentStoreUbiquitousContentNameKey 键到文档的 persistentStoreOptions 属性。这个键的值就是你在第2步中获取的值
  5. 调用文档对象的 openWithCompletionHandler: 方法来打开文档

应 用第一次打开其它设备创建的Core Data文档时,Core Data会自动检测到SQLite store不存在,并在本地创建一个。然后使用 NSPersistentStoreUbiquitousContentNameKey 键的值(你添加到属性的那个)来获取适当的transaction logs,并重新构建数据库的内容。从这时候开始,你就可以修改该文档并保存到iCloud。你所做的修改会保存到新的log file,这样其它设备就能将其整合到它们的SQLite store。


当应用从iCloud中 接收到文档修改时,Core Data会自动将这些修改合并到文档的SQLite store,并给应用发 送 NSPersistentStoreDidImportUbiquitousContentChangesNotification 通知。应用必须注册这个通知,并使用它来刷新任何修改的记录。如果应用不刷新本地的数据拷贝,就会将老的修改重新写到iCloud,并产生一个冲突版本。通过及时地整合其它设备的修改,应用就能避免类似的冲突。


删 除一个文档时,你必须同时删除文档的file package,以及包含文档transaction logs的目录。同时删除所有这些东西,要求你使用 NSFileCoordinator 对象来执行coordinated写入操作。文档的DocumentMetadata.plist 文件包含一个 NSPersistentStoreUbiquitousContentURLKey 键,它的值就是文档transaction logs目录的URL。


使用Core Data管理中央库(Central Library)
如果应用使 用Central Core Data store来管理数据,就应该将data store直接存放在应用Sandbox目录。使用一个Central data store的应用,通常只有一个persistent store coordinator对象和一个persistent store对象。因此,最简单的解决办法是将Core Data store保留在应用Sandbox,仅使用iCloud来同步修改。


在本地创建SQLite store时,执行以下步骤:

  1. 创 建data store时,调用 addPersistentStoreWithType:configuration:URL:options:error: 方法,并在传递的options Dictionary中包含 NSPersistentStoreUbiquitousContentNameKey 和 NSPersistentStoreUbiquitousContentURLKey 键。
  2. 注册 NSPersistentStoreDidImportUbiquitousContentChangesNotification 通知,并使用它来更新所有的记录更新。

因为你只有一个data store,你可以为 NSPersistentStoreUbiquitousContentNameKey 键指定任何名字。对于 NSPersistentStoreUbiquitousContentURLKey 键,应该指定为应用某个iCloud容 器目录中的某个目录URL。换句话说,这个URL应该基于 URLForUbiquityContainerIdentifier: 方法返回的URL构造而成。Core Data将修改写入到你指定的这个目录,其它设备则在这个目录中查找修改。当检测到修改时,Core Data会自动整合修改到本地的SQLite store,并通知你的应用。


同样,你也必须及时地响应iCloud相关的修改通知。这些通知使应用能确保使用最新的数据,如果你使用老版本的数据,就可能覆盖其它设备的新数据,并产生冲突版本。


为Core Data Transaction Logs指定自定义位置
应用Core Data Store的修改使用transaction logs来保存,这些logs存储在用户iCloud账户的一个特殊目录中。应用的所有Core Data Stores全部使用同一个目录来保存transaction logs。默认情况下,这个目录的名字和应用bundle ID相同,并保存在应用默认iCloud容器目录中。如果你已经使用这个目录作为其它用途,你可以通过修改Core Data stores的选项来修改目录的名字。


在 基于文档的应用中,要自定义transaction logs目录,必须修改每个 UIManagedDocument 对象的 persistentStoreOptions 属性Dictionary。在字典中增加 NSPersistentStoreUbiquitousContentURLKey 键,并设置值为你希望使用的自定义目录URL。这个URL需要首先使用 URLForUbiquityContainerIdentifier: 方法,并通过添加额外的路径来扩展URL。


如果应用使用单一的Core Data store管理所有数据,在创建 persistent store时,调用 addPersistentStoreWithType:configuration:URL:options:error: 方法,并在options参数中增加  NSPersistentStoreUbiquitousContentURLKey 键,值也是你希望设置的目录URL。




使用iCloud Key-Value Data Storage
应用使用iCloud Key-Value data storage来存储参数、或小量的非关键配置数据。key-value data storage概念上类似于本地user defaults数据库,应用通常用来存储配置。区别在于iCloud数据在用户所有设备中你的所有应用实例间共享。


使 用 NSUbiquitousKeyValueStore 类需要设置"com.apple.developer.ubiquity-kvstore-identifier" Entitlement,如果多个不同的应用配置相同的entitlement值,则这些应用都可以共享相同的key-value数据。


使用 NSUbiquitousKeyValueStore 类写入数据到iCloud key-value store,这个类概念上也类似于 NSUserDefaults,用于保存和获取简单的数据类型:数字、字符串、日期、数组等等。


应 用的key-value store的容量限制为64KB(而每个键的限制当前也是64KB)。因此应用只能使用key-value storage记录很少的数据,不能用于存储用户文档或其它大型数据archive。典型的例子是杂志应用,可以保存用户当前阅读的刊物和页数。这样用户 在其它设备打开相同应用时,就能回到之前阅读的位置。


NSUbiquitousKeyValueStore 类绝对无法代替 NSUserDefaults 类,应用总是应该通过 NSUserDefaults 将所有配置数据保存在本地磁盘。然后再使用 NSUbiquitousKeyValueStore 将需要共享的数据上传到key-value store。这样确保iCloud不可用时,你仍然能够访问应用的配置数据。




负责任的iCloud App
用户的iCloud空间有限,并且由所有应用共享。用户可以查看指定应用消耗的iCloud空间,可以选择删除应用相关联的文档和数据。因此,应用必须对自己存储在iCloud中的文件负责,下面是一些管理iCloud文档的建议:

  • 对存储iCloud文档采取一种好的策略。允许用户启用或禁用iCloud
  • 从用户iCloud账户中删除一个文档,将从用户所有计算机和设备中删除该文档。确保用户明白这一点,并确认删除操作。如果你只是想刷新文档的本地拷贝,使用 NSFileManager 的 evictUbiquitousItemAtURL:error: 方法,而不是删除文件。
  • 存储文档到iCloud时,尽量将文档存储在"Documents"子目录中。用户可以单个删除Documents目录中的文档以释放空间,但是Documents目录之外的所有东西,都被当做数据,只能一次全部删除!
  • 永远不要存储缓存或其它应用的私有文件到用户的iCloud storage。用户的iCloud账户只应该用于存储用户相关的数据,以及应用无法重新生成的内容。
  • iCloud文件和应用Sandbox文件相同对待。保存文件应该由应用需求和保留用户数据的需求来驱动。你不应该修改应用更频繁或更慢地保存iCloud文件。iCloud会自动优化自己向服务器的传输,以确保最佳的性能。

转载于:https://www.cnblogs.com/ligun123/archive/2012/03/22/2411112.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/409988.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

0x00000000指令引用的内存不能为written_变量和内存访问

计算机世界有一个常识——所有的数据和指令必须经由内存才能进入CPU的寄存器进而被CPU使用&#xff0c;那么我们程序操作的主战场就是内存&#xff0c;内存操作也就顺理成章成为了程序中最高频的操作。为了节目的效果&#xff0c;我们先来看一段8086平台下的汇编代码&#xff1…

Zabbix 3.0 配置企业微信报警(注册---测试)

一、申请企业微信 1、登录企业微信官网&#xff0c;点击企业注册 二、配置企业微信 1、邀请管理员使用企业微信&#xff0c;如果有多个人直接添加新成员 2、管理员收到邀请&#xff0c;下载手机版企业微信&#xff0c;使用微信号登陆即可 3、创建应用 4、填写应用信息&#xff…

AutoMapper 9.0的改造(续)

上一篇有一个读者&#xff0c;有疑问&#xff0c;如何自动化注册Dto 我开篇&#xff0c;做了一个自动化注册的 public sealed class AutoInjectAttribute : Attribute{public Type SourceType { get; }public Type TargetType { get; }public AutoInjectAttribute(Type sourceT…

.net byte转java byte_Java Web安全 || Java基础 Java Agent

点击上方“凌天实验室”&#xff0c;“星标或置顶公众号”漏洞、技术还是其他&#xff0c;我都想第一时间和你分享“【历史】已连载更新全部内容&#xff1a;【菜单栏】-【JAVA SEC】01Java AgentJDK1.5开始&#xff0c;Java新增了Instrumentation(Java Agent API)和JVMTI(JVM …

必须进行支持的游戏方可使用此功能_C#8.0 新增功能

(给DotNet加星标&#xff0c;提升.Net技能)转自&#xff1a;张传宁cnblogs.com/SavionZhang/p/11201818.htmlC#8.0提供了许多增强功能1、Readonly 成员可将 readonly 修饰符应用于结构的任何成员。它指示该成员不会修改状态。这比将 readonly 修饰符应用于 struct 声明更精细。…

Zabbix 3.0 配置企业微信报警(配置zabbix-web)

一、添加报警媒体类型 Name&#xff1a;自定义 Type&#xff1a;选择script Scripts name&#xff1a;填写脚本名称 Script parameters&#xff1a;脚本参数--corpidXXX--corpsecretXXX--user{ALERT.SENDTO}--msg{ALERT.MESSAGE}--agentidXXX最后点Add即可添加完成&#xff1b;…

采用python解决实际问题_Python编程语言解决几种常见的实际问题

Python编程语言解决几种常见的实际问题 (2012-10-25 17:24:12) 标签&#xff1a; it python python培训 北京 杂谈 Python编程语言解决一些实际问题 from os.path import walk, join, normpath from os import chdir, remove def scan(arg, dirname, names) for file in names:…

EevExpress中XtraGrid常用方法

1.girdView在第一列显示行号 调整第一列的宽度 gridView1.IndicatorWidth 40; View Code 1 private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e)2 { 3 if (e.Info.IsRowIndi…

【转载】博客园编辑数学公式的方法

原文在这里&#xff1a;博客园编辑数学公式的方法 需要在选项中勾上 启用数学公式支持 在公式开始和结尾输入美元符号 &#xff1a; 如 美元符号x^2美元符号 则显示x的平方 x^2 需要在http://latex.codecogs.com/eqneditor/editor.php里面编辑好后复制源码过来。 如 转载于:htt…

php代码里怎么写html代码_菜鸟青铜变白银!Python 项目代码写完了,然后怎么打包和发布?...

你把你的代码写完了&#xff0c;是不是要给别人使用下&#xff0c;怎么打包你的项目代码呢&#xff1f;喂&#xff0c;开源么&#xff1f;接下来小帅b就跟你说说&#xff0c;如何打包你的代码。就拿我们上次演示的 todo为例&#xff0c;写完代码之后&#xff0c;代码的目录是这…

三次样条插值 cubic spline interpolation

什么是三次样条插值 插值&#xff08;interpolation&#xff09;是在已知部分数据节点&#xff08;knots&#xff09;的情况下&#xff0c;求解经过这些已知点的曲线&#xff0c; 然后根据得到的曲线进行未知位置点函数值预测的方法&#xff08;未知点在上述已知点自变量范围内…

vscode python环境_在vscode中配置python环境

原博文 2019-09-27 22:55 − 1.安装vscode和python3.7&#xff08;安装路径在&#xff1a;E:\Python\Python37&#xff09;&#xff1b; 2.打开vscode&#xff0c;在左下角点击设置图标选择setting&#xff0c;搜索python path&#xff0c;在该路径下选择python的安装路径&…

ufw防火墙规则不生效

正式站系统是Ubuntu 16.04.6 一、今天一个项目有百度爬出&#xff0c;在nginx中封掉还在一直爬取&#xff0c;都403还不停爬取 二、在uwf封掉爬出ip&#xff0c;想封掉80端口没有用&#xff0c;然后封掉整个网段还是没有用&#xff0c;尴尬 三、放出终极大招 UFW(iptables)规则…

network怎么断点调试_Windows 网络编程:调试 API

一次性进群&#xff0c;长期免费索取教程&#xff0c;没有付费教程。教程列表见微信公众号底部菜单进微信群回复公众号&#xff1a;微信群&#xff1b;QQ群&#xff1a;460500587微信公众号&#xff1a;计算机与网络安全ID&#xff1a;Computer-network在Windows中有这么一些AP…

非会员只能试看20分钟_做欧包都要把铁锅烤半小时?太费电了,用我这办法只需预热几分钟...

最近迷上了做欧包&#xff0c;做欧包要用蒸烤箱&#xff0c;做好的欧包才会外脆内软&#xff0c;如果没有蒸烤箱的话人们又研究出了用铸铁锅来做&#xff0c;先把铸铁锅放在烤箱里烘烤半小时左右&#xff0c;然后把面包坯子放入铸铁锅盖好盖子迅速放回烤箱&#xff0c; 因为锅的…

顺序表归并

对两个顺序表进行合并。 思想&#xff1a;定义两个变量&#xff08;i&#xff0c;j&#xff09;分别指向顺序表 A和B当前处理的元素&#xff0c;若i元素不大于j元素&#xff08;<&#xff09;&#xff0c;则把i元素复制到新表中&#xff0c;否者将j元素复制到新表中。 View …

collection集合 多少钱_Java集合框架大汇总,建议收藏

Java集合Java集合框架&#xff1a;是一种工具类&#xff0c;就像是一个容器可以存储任意数量的具有共同属性的对象。Java集合中成员很丰富&#xff0c;常用的集合有ArrayList&#xff0c;HashMap&#xff0c;HashSet等。线程安全的有Vector&#xff0c;HashTable。线程不安全的…

python识别简单训练模型_使用已经得到的keras模型识别自己手写的数字方式

环境&#xff1a;Pythonkeras&#xff0c;后端为Tensorflow 训练集&#xff1a;MNIST 对于如何训练一个识别手写数字的神经网络&#xff0c;网上资源十分丰富&#xff0c;并且能达到相当高的精度。但是很少有人涉及到如何将图片输入到网络中并让已经训练好的模型惊醒识别&#…

程旭元系统漫画第三期:加班 !

对于苦逼的程旭元来说 加班已经变成了生活中不可缺少的部分 他的原则是不能像胖子那样贪吃 不能像销售员那样狡诈 一定要尽忠职守 精忠报国 &#xff01;老板说什么他就做什么&#xff01; 对于一个从来只说加班不加工资的boss来说 唯命是从就是存活在公司的最好方式~ 但是有…