iCloud详解——基础篇

大家好,指北君又来,今天,指北君决定带领大家当一把高富帅,什么是高富帅?当然是“用Mac-学Go-开发iOS”,是不是感觉和指北君一向的标签出入太大,各位小伙伴不要惊慌,技术无界限,指北君只是学习并向小伙伴介绍下iCloud的原理,不涉及代码。

前言

iCloud使得用户的个人内容可以在用户的所有设备上使用,iCloud不仅为苹果自身的应用所使用,第三方应用也可接入使用。iCoud基于最基础的iCloud账户,第三方应用开发者可以按照iCloud的开发文档来为自己的应用设计多设备数据使用方式。 本篇文章将主要介绍iCloud键值存储和文档存储的基本元素,对于更深入的内容参考相关的资料。 应用程序使要使用iCloud需要启用iCloud 服务。

安全数据传输

开发者的应用程序不会直接与 iCloud 服务器通信,操作系统会管理用户设备上的iCloud账户,并负责应用和iCloud服务器之间的数据上传和下载。关键的流程如下:

  1. 配置应用程序的iCloud容器的访问权限。包含请求权利和容器初始化(使用之前)。
  2. 应用程序响应iCloud事件(回调)。比如:用户退出 iCloud,文件位置的变化(该应用的数据在其他设备上重命名、移动、复制或被删除文件)。
  3. 在应用中使用API进行读写。
  4. 操作系统根据需要协调与 iCloud 之间的数据传输。 iCloud 服务在传输之前对数据进行加密,iCloud 服务器继续以加密格式存储数据。iCloud使用安全令牌进行身份验证。iCloud数据安全和隐私参阅相关内容。

容器、存储和权限

要将数据保存到 iCloud,应用程序需要将数据存放到iCloud 容器中(特殊文件系统位置),iCloud的容器是iCloud存储的本地的映射,它与应用程序的其余数据分开,如下图:

iCloud容器

要启用对任何 iCloud 容器的访问,需要请求适当的权限。

使用 Xcode 功能请求访问 iCloud

Xcode 项目的功能选项卡管理应用程序iCloud权限和容器创建。启用 iCloud 功能后,Xcode 创建一个权限文件(如果尚不存在)并配置好对应的服务和权限。开发者还可以使用Xcode配置其他事项,比如创建关联容器。 当启用 iCloud 文档时,Xcode配置应用程基于应用ID来访问iCloud 容器。大多数应用只需访问默认容器。如果应用程序之间需要共享数据,需要将目标配置为共享容器。当一个应用访问多个容器 ID 时,列表中的第一个ID必须为主容器。在 OS X 中,它也是在NSDocument打开和保存对话框中显示内容的容器。

配置通用容器

在Xcode中,可以根据应用需要访问任意数量的iCloud容器。如果希望多个应用程序共享文档,此功能非常有用。比如,如果开发者提供应用的免费和付费版本,开发者希望用户在从免费版本升级到付费版本时保留iCloud文档的访问权限,在这种情况下,将两个应用配置为同一个iCloud容器。

配置通用的 iCloud 容器

  1. 选择多个应用中的一个指定为主应用,该应用的iCloud容器作为通用容器。比如,对于免费和付费应用,可以将付费应用指定为主要应用。
  2. 每个应用启用iCloud功能。
  3. 配置主应用仅使用默认容器。
  4. 对每个辅助应用程序,启用“指定自定义容器标识符”选项并将主应用的容器标识符添加到容器列表中。 当主要和次要应用程序中读取和写入文件时,仅在公共存储容器中构建 URL 和搜索文件。要检索公共存储容器的URL,请将主应用程序的容器标识符传递给URLForUbiquityContainerIdentifier:NSFileManager。不要传递nil给该方法,这样做会返回应用程序的默认容器,每个应用程序的默认容器都不同。显式指定容器标识符可以确保不会出错。

配置通用键值存储

如果您提供免费和付费两个版本的应用,并希望为两者使用相同的键值存储,你可以这样做。

配置通用键值存储

  1. 将您支持 iCloud 的应用之一指定为主应用。该应用的iCloud容器成为通用容器。例如,对于免费和付费应用,将付费应用指定为主要应用。
  2. 为每个应用启用 iCloud 功能。
  3. 为两个应用启用键值存储选项。Xcode 会自动为每个应用添加授权,并根据应用的捆绑ID分配一个iCloud容器。
  4. 对于除主应用程序之外的所有应用,在应用程序.entitlements文件中手动更改 iCloud 容器ID。将com.apple.developer.ubiquity-kvstore-identifier的值设置为主应用的ID。

iCloud 容器具有最小结构

新创建的iCloud容器结构只有一个Documents子目录。对于文档存储,可以任何方式排列容器内的文件。开发者可以根据应用程序的需要定义结构,包含在容器顶层添加自定义目录和自定义文件,如图所示。

iCloud容器目录结构

可以在Documents目录中创建文件和目录,可以在自身创建的任何目录中创建文件或目录。使用NSFileManager来完成对应的操作,详细参考API文档。 Documents目录作是iCloud容器的对外展示窗口。当用户检查应用对应的iCloud存储时(使用iOS中的设置或OS X中的系统偏好设置),Document子目录中的文件或文件包会被列出并可单独删除。子目录之外的文件Documents被视为应用的私有文件。如果用户想要删除Documents目录之外的任何内容,他们必须删除子目录之外的所有内容。

查看iCloud存储的视图的操作步骤(需要确保至少安装了一个支持iCloud的应用):

  • 在 iOS 中,打开设置。然后导航到 iCloud > 存储和备份 > 管理存储。
  • 在 OS X 中,打开系统偏好设置。然后打开 iCloud 偏好设置面板并点按“管理”。

iCloud存储策略

每个iCloud用户可以免费使用一定的存储空间,并且可以根据需要购买更多。由于此空间由用户启用 iCloud 的 iOS 和 Mac 应用共享,因此拥有多个应用的用户可能会耗尽空间。用户可以根据自身需要选择需要保存到iCloud上的应用。一般来说可以按照下面的建议来操作:

建议使用iCloud的内容:

  1. 用户文档
  2. 包含用户创建数据的特定于应用程序的文件
  3. 首选项和应用程序状态(使用键值存储,不计入用户的 iCloud 存储分配)
  4. 更改 SQLite 数据库的日志文件(不得将 SQLite 数据库的存储文件存储在 iCloud 中)

不建议使用iCloud的内容

  1. 缓存文件
  2. 临时文件
  3. 您的应用程序创建并可重新创建的应用程序支持文件
  4. 下载的大数据文件

有时,用户可能想要从 iCloud 中删除内容,需要通过界面提示用户该文档将从iCloud帐户和所有设备中删除,并且为用户提供取消删除的机会。 可以通过添加.nosync后缀来防止文件和目录存储在iCloud,当iCloud在本地容器目录中遇到带有该扩展名的文件和目录时,会跳过这些文件或目录。可以在要存储在文件包中的临时文件上使用此扩展名。尽管带有.nosync扩展名的项目不会传输到服务器,但它们仍绑定到其父目录。当您在iCloud中删除父目录时,或者在本地删除父目录及其内容时,该目录的全部内容都会被删除,包括任何.nosync项目。

系统管理本地 iCloud 存储

iCloud数据存在于Apple的iCloud服务器上,但系统在每个用户的设备上维护数据的本地缓存,如图所示。iCloud数据的本地缓存允许用户在网络不可用时继续工作,例如当他们打开飞行模式时。

iCloud文件

iCloud数据的本地缓存与设备上的其他文件共享空间,在存储空间不足时,系统通过优化存储子集来解决这个问题。系统在本地保存完整的文件元数据,确保应用的用户可以访问他们的所有文件,无论文件是否在本地。比如,一个文件长久未使用,而又有一个新文件需要本地空间,则系统可能会从iCloud容器中回收该文件。更新后元数据仍然是本地的,用户仍然可以看到被释放文件的名称和其他信息,如果连接到网络,可以打开它。

应用管理本地存储

基于文档的应用通常不需要管理iCloud文件在本地回收处理,系统拥有统一文件回收机制。开发者也可以通过下面两个方式辅助管理本地存储:

  1. 主动回收。如果可以明确该文件一段时间都不再使用,可以通过调用NSFileManager: evictUbiquitousItemAtURL方法从iCloud容器中显式回收。【注意】谨慎使用此方法,明确用户需求,一旦文件回收,系统必须再次下载该文件,然后您的应用才能使用它。
  2. 相反,如果明确希望确保文件在本地可用,可以初始启动iCloud容器的下载,对应方法为 NSFileManager: startDownloadingUbiquitousItemAtURL。

总结

以上就是指北君对iCloud的一个基本机制的介绍,帮助小伙伴理解iCloud如何实现多设备之间的数据同步和管理。

我是指北君,操千曲而后晓声,观千剑而后识器。感谢各位人才的:点赞、收藏和评论,我们下期更精彩!

Java Geek Tech wechat
欢迎订阅 Java 技术指北,这里分享关于 Java 的一切。