• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

使用CloudKit构建购物清单应用程序

早在 2012 年,Apple 就在 ios 5 中引入了 icloud。同时,该公司宣布开发者将可以通过多个api访问 iCloud 。起初,开发者有三个选择:

  • 键值存储

  • 文件存储

  • 核心数据集成

但是,这些 API 并不完美。一个主要缺点是缺乏透明度。尤其是核心数据集成,  即使是最有经验的开发人员也会感到沮丧和困惑。当出现问题时,开发人员不知道罪魁祸首是什么或谁。这可能是他们的代码或 Apple 的问题。

CloudKit

在 WWDC 2014 上,Apple 推出了 CloudKit,这是一个全新的框架,可直接与 Apple 的 iCloud 服务器交互。该框架可与许多 PaaS  (平台即服务)解决方案相媲美,例如firebase。与 Firebase 一样,Apple 提供了一个灵活的 API 和一个仪表板,让开发人员可以查看存储在 Apple iCloud 服务器上的数据。

我最喜欢 CloudKit 的地方在于 Apple 自己对该框架的承诺。据该公司称,  iCloud Drive 和 iCloud Photo Library 是建立在 CloudKit 之上的。这表明 CloudKit 框架及其基础设施是健壮和可靠的。

作为开发人员,这种信任和承诺的标志很重要。过去,Apple 偶尔会发布受 bug 困扰或缺乏关键功能的 API,这仅仅是因为该公司不吃自己的狗粮。CloudKit 并非如此。这是有希望的。

你应该使用 CloudKit 吗?

键值存储和文档存储有其用途,Apple 强调 CloudKit 不会取代或弃用现有的 iCloud API。核心数据也是如此。例如,CloudKit 不提供本地存储。这意味着在没有网络连接的设备上运行的应用程序如果仅依赖于 CloudKit 将毫无用处。

Apple 还强调错误处理在使用 CloudKit 时至关重要。例如,如果保存操作失败,并且用户没有收到通知,那么她甚至可能不知道她的数据没有保存——并且丢失了。

CloudKit 是在云端存储结构化和非结构化数据的绝佳解决方案。如果您需要一个解决方案来访问多个设备上的数据,那么 CloudKit 无疑是一个值得考虑的选择。

在 2015 年的 WWDC 上,Apple 做了很少有开发者期待或希望的事情。它宣布了 CloudKit 的网络服务。这意味着 CloudKit 几乎可以在任何平台上使用,包括android和 Windows Phone。

苹果的定价也 很有竞争力 。CloudKit 入门是免费的,并且对于大多数应用程序来说仍然是免费的。同样,如果您打算将数据存储在云中,CloudKit 肯定值得考虑。

CloudKit 概念

与 Core data 苦苦挣扎的开发人员通常不熟悉框架的构建块。如果你不花时间去了解和理解 Core Data 堆栈,那么你将不可避免地遇到问题。CloudKit 也是如此。

在我们开始使用 CloudKit 的示例应用程序之前,我想花几分钟时间向您介绍 CloudKit 框架和基础架构的一些关键概念。让我们从容器、数据库和沙盒开始。

隐私和遏制

Apple 明确表示隐私是 CloudKit 的一个重要方面。首先要知道的是,每个应用程序在 iCloud 中都有自己的容器。这个概念与每个 iOS 应用程序都有自己的沙箱非常相似。但是,可以与其他应用程序共享一个容器,只要这些应用程序与同一个开发者帐户相关联。正如您可以想象的那样,这为开发人员打开了许多有趣的可能性。

一个 CloudKit 容器包含多个数据库。每个容器都有一个公共数据库,可用于存储应用程序的每个用户都可以访问的数据。除了公共数据库之外,容器还为应用程序的每个用户包含一个私有数据库。用户的私有数据库用于存储特定于该特定用户的数据。数据隔离和封装是 CloudKit 和 iCloud 基础架构的关键组件。

尽管应用程序的容器可以保存许多数据库,但从开发人员的角度来看,一个容器只保存两个数据库: 公共数据库 和  当前登录到其 iCloud 帐户的用户的私有数据库。截至 2017 年,Apple 推出了第三个数据库 shared database,使应用程序能够共享在另一个用户的私人数据库上共享的记录子集,并邀请他们为这些公开的记录做出贡献。 

使用CloudKit构建购物清单应用程序  第1张

稍后我将详细讨论 iCloud 帐户。

记录和记录区

应用程序容器存储记录的数据库。这与传统数据库没有太大区别。乍一看,存储在 CloudKit 数据库中的记录似乎只不过是键值对字典的包装器。它们可能看起来像美化的字典,但这只是故事的一部分。

每条记录也有一个 记录类型 和一些 元数据 字段。记录的元数据会跟踪记录的创建时间、创建记录的用户、记录的最后更新日期以及更新记录的人员。

该类 CKRecord 代表了这样一个记录,并且它是一个非常强大的类。您可以存储在记录中的值不限于属性列表类型。您可以将字符串、数字、日期和数据块存储在记录中,但 CKRecord 该类还将位置数据 , CLLocation视为第一类数据类型。

您甚至可以在记录中存储支持的数据类型的数组。换句话说,字符串或数字的数组对于 CKRecord 实例来说是没有问题的。

记录在记录区中组织。记录区对相关记录进行分组。公共和私有数据库各有一个默认记录区,但如果需要,可以创建自定义记录区。记录区是一个高级主题,我们不会在本系列中详细讨论。

关系

记录之间的关系由 CKReference 类的实例管理。让我们看一个例子来更好地理解关系是如何工作的。我们将在本系列中创建的应用程序将管理许多购物清单。每个列表中可以包含零个或多个项目。这意味着每个项目都需要引用它所属的列表。

使用CloudKit构建购物清单应用程序  第2张

重要的是要了解该项目保留对列表的引用。虽然可以为 CKReference 列表中的项目创建实例数组,但更方便且推荐使用项目的外键,而不是列表。这也是苹果推荐的。

CloudKit 管理关系的方式相当基本,但它确实提供了一个选项,可以在删除父记录时自动删除记录的子记录。我们将在本系列的稍后部分仔细研究关系。

资产

我还想提一下 CKAsset 班级。虽然可以将数据块存储在记录中,但非结构化数据(例如图像、音频和视频)应作为 CKAsset 实例存储。一个 CKAsset 实例总是与一条记录相关联,它对应于磁盘上的一个文件。在本系列中,我们不会使用 CKAsset 该类。

验证

我相信你同意 CloudKit 看起来很吸引人。然而,有一个重要的细节我们还没有讨论:身份验证。用户通过他们的 iCloud 帐户进行身份验证。未登录 iCloud 帐户的用户无法将数据写入 iCloud。

虽然这适用于任何 iCloud API,但请记住,在这种情况下,仅依赖 CloudKit 的应用程序将无法正常工作。如果开发人员允许,用户所能做的就是访问公共数据库中的数据。

读取数据

未登录其 iCloud 帐户的用户仍然可以从公共数据库中读取数据。不用说私有数据库是不可访问的,因为 iCloud 不知道谁在使用该应用程序。

读写

登录后,用户可以读取和写入公共及其私有数据库。我已经提到苹果非常重视隐私。因此,存储在私有数据库中的记录只能由用户访问。即使是您,开发人员,也看不到用户存储在其私有数据库中的数据。这是 Apple 管理应用程序后端的缺点,但对用户来说无疑是一个胜利。

购物清单

我们即将构建的应用程序将管理您的购物清单。每个购物清单都有一个名称和零个或多个项目。构建购物清单应用程序后,您应该会觉得在自己的项目中使用 CloudKit 框架很舒服。

先决条件

对于本教程,我将使用 Xcode 9 和 swift 4。如果您使用的是旧版本的 Xcode,请记住您使用的是不同版本的 Swift 编程语言。这意味着您将需要更新项目的源代码以满足编译器的要求。这些变化大多很小,但重要的是要意识到这一点。

因为 CloudKit 是一个高级主题,所以我假设您熟悉 Xcode 和 Swift 编程语言。如果您是 iOS 开发新手,那么我建议您先阅读入门教程或参加我们的 Swift 开发课程之一:

如果您不熟悉 iOS 开发或 Swift 语言,请务必查看这些内容。

项目设置

是时候开始编写一些代码了。启动 Xcode 并基于 Single View Application 模板创建一个新项目。

使用CloudKit构建购物清单应用程序  第3张为您的项目 命名 和 组织标识符。生成的包标识符将用于创建应用程序默认容器的标识符。该标识符在开发人员帐户之间必须是唯一的,因为它们共享一个全局命名空间。因此,遵循 Apple 的建议并使用 反向域名表示法很重要。

使用CloudKit构建购物清单应用程序  第4张

启用 iCloud

下一步是启用 iCloud 和 CloudKit。 在左侧的Project Navigator中选择项目, 然后从目标列表中为您的应用程序选择目标。打开 常规 选项卡并将 团队设置 为正确的团队。为避免在下一步出现任何问题,请验证您的开发者帐户是否具有创建App ID所需的权限 。

使用CloudKit构建购物清单应用程序  第5张接下来,打开  顶部 的功能选项卡并将iCloud的开关设置为 打开。Xcode 将需要一点时间来  代表您创建一个App ID 。它还将向 App ID 添加必要的权利。如果这不起作用,请确保团队设置正确并且您拥有创建 App ID 所需的权限。

使用CloudKit构建购物清单应用程序  第6张

启用 CloudKit 就像选中标记为CloudKit的复选框一样简单 。默认情况下,您的应用程序将为您的应用程序使用默认容器。当您启用 CloudKit 时,会自动为您创建此容器。

如果您的应用程序需要访问不同的容器或多个容器,请选中标有“ 指定自定义容器”的复选框 并选中您的应用程序需要访问的容器。

使用CloudKit构建购物清单应用程序  第7张您可能已经注意到 Xcode 已自动将您的目标链接到 CloudKit 框架。这意味着您已准备好开始在您的应用程序中使用 CloudKit。

弄湿你的脚

在本系列的下一个教程中,我们将添加添加、编辑和删除购物清单的功能。然而,为了完成本教程,我想通过向您展示如何与 CloudKit API 交互来让您体验一下。我们要做的就是获取当前登录用户的记录。

打开 ViewController.swift 并在顶部添加一个 import 语句来导入 CloudKit 框架。

import UIKit
import CloudKit

要获取用户记录,我们首先需要获取记录的标识符。让我们看看这是如何工作的。我创建了一个辅助方法 , fetchUserRecordID以包含用于获取用户记录标识符的逻辑。我们在视图控制器的方法中调用此 viewDidLoad 方法。

override func viewDidLoad() {
    super.viewDidLoad()

    // Fetch User Record ID
    fetchUserRecordID()
}

的实现 fetchUserRecordID 比 viewDidLoad. defaultContainer 我们首先通过调用类来获取对 应用程序默认容器的引用 CKContainer 。然后我们调用 fetchUserRecordIDWithCompletionHandler(_:) . defaultContainer这个方法接受一个闭包作为它的唯一参数。

private func fetchUserRecordID() {
        // Fetch Default Container
        let defaultContainer = CKContainer.default()
        
        // Fetch User Record
        defaultContainer.fetchUserRecordID { (recordID, error) -> Void in
            if let responseError = error {
                print(responseError)
                
            } else if let userRecordID = recordID {
                DispatchQueue.main.sync {
                    self.fetchUserRecord(recordID: userRecordID)
                }
            }
        }
    }

闭包接受两个参数:一个可选 CKRecordID 实例和一个可选 NSError 实例。如果 error 是 nil,我们安全地打开包装 recordID。

重要的是要强调闭包将在后台线程上调用。这意味着在 CloudKit 调用的闭包中更新应用程序的用户界面时需要小心。fetchUserRecordID例如,我在主线程上显式 调用 fetchUserRecord(_:) 。

在 fetchUserRecord(_:)中,我们通过告诉 CloudKit 我们感兴趣的记录来获取用户记录。请注意,我们调用 fetchRecordWithID(_:completionHandler:) 了 privateDatabase 对象,该对象的属性 defaultContainer 。

该方法接受一个 CKRecordID 实例和一个完成处理程序。后者接受一个可选 CKRecord 实例和一个 NSError 实例。如果我们成功获取了用户记录,我们将它打印到 Xcode 的控制台

private func fetchUserRecord(recordID: CKRecordID) {
        // Fetch Default Container
        let defaultContainer = CKContainer.default()
        
        // Fetch Private Database
        let privateDatabase = defaultContainer.privateCloudDatabase
        
        // Fetch User Record
        privateDatabase.fetch(withRecordID: recordID) { (record, error) -> Void in
            if let responseError = error {
                print(responseError)
                
            } else if let userRecord = record {
                print(userRecord)
            }
        }
    }

当您在 Xcode 中运行应用程序时,您将在控制台中看到类似于以下内容的内容:

使用CloudKit构建购物清单应用程序  第8张这应该让您对 CloudKit 框架有所了解。它的现代 API 直观且易于使用。在下一个教程中,我们将深入挖掘 CloudKit API 的可能性。

您可以在GitHub  (tag #introduction)上克隆完整的示例项目 。

结论

您现在应该对 CloudKit 框架的基础有了正确的了解。本系列的其余部分将重点关注构建购物清单应用程序。在下一个教程中,我们将从添加添加、编辑和删除购物清单的功能开始。


文章目录
  • CloudKit
  • 你应该使用 CloudKit 吗?
  • CloudKit 概念
    • 隐私和遏制
    • 记录和记录区
    • 关系
    • 资产
    • 验证
      • 读取数据
      • 读写
  • 购物清单
    • 先决条件
    • 项目设置
    • 启用 iCloud
    • 弄湿你的脚
  • 结论