前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Core Data with CloudKit (一) —— 基础

Core Data with CloudKit (一) —— 基础

作者头像
东坡肘子
发布2022-07-28 12:48:25
9900
发布2022-07-28 12:48:25
举报
文章被收录于专栏:肘子的Swift记事本

Core Data with CloudKit (一) —— 基础

这是系列文章的第一篇,该Core Data with CloudKit系列主要介绍了如何使用CoreData同步CloudKit的三种数据库类型:私有数据库、公共数据库、共享数据库。如果想获得更好的阅读体验,可以直接访问我的个人博客 www.fatbobman.com[1]

在WWDC 2019上,苹果为Core Data带了一项重大的更新——引入了NSPersistentCloudKitContainer。这意味着无需编写大量代码,使用Core Data with CloudKit可以让用户在他所有的苹果设备上无缝访问应用程序中的数据。

Core Data为开发具有结构化数据的应用程序提供了强大的对象图管理功能。CloudKit允许用户在登录其iCloud账户的每台设备上访问他们的数据,同时提供一个始终可用的备份服务。Core Data with CloudKit则结合了本地持久化+云备份和网络分发的优点。

2020年、2021年,苹果持续对Core Data with CloudKit进行了强化,在最初仅支持私有数据库同步的基础上,添加了公有数据库同步以及共享数据库同步的功能。

我将通过几篇博文介绍Core Data with CloudKit的用法、调试技巧、控制台设置并尝试更深入地研究其同步机制。

Core Data with CloudKit的局限性

只能运行在苹果的生态不同于其他的跨平台解决方案,Core Data with CloudKit只能运行于苹果生态中,并且只能为苹果生态的用户提供服务。•测试门槛较高需要有一个Apple Developer Program[2]账号才能在开发过程中访问CloudKit服务和开发团队的CKContainer。另外,在模拟器上的运行效果也远没有在真机上可靠。

Core Data with CloudKit的优点

几乎免费开发者基本上不需要为网络服务再额外支付费用。私有数据库保存在用户个人的iCloud空间中,公共数据库的容量会随着应用程序使用者的增加而自动提高,最高可增加到1 PB 存储、10 TB 数据库存储,以及每天 200 TB 流量。之所以说几乎免费,毕竟苹果会扣取15-30%的app收益。•安全一方面苹果通过沙盒容器、数据库区隔、加密字段、鉴权等多种技术手段保证了用户的数据安全。另一方面,鉴于苹果长期以来在用户中树立的隐私捍卫者的形象,使用Core Dat with CloudKit可以让用户对你的应用程序增加更多的信任。事实上,正是在WWDC2019年看到这个功能后,我才有了开发【健康笔记】[3]的原动力——既保证数据隐私又能长久的保存数据。•集成度高、用户感知好鉴权、分发等都是无感的。用户不需要进行任何额外的登录便可享受全部的功能。

Core Data

Core Data诞生于2005年,它的前身EOF在1994年便已经获得的不少用户的认可。经过了多年的演进,Core Data已经发展的相当成熟。作为对象图和持久化框架,几乎每个教程都会告诉你,不要把它当作数据库,也不要把它当作ORM

Core Data的功能包括但不限于:管理序列化版本、管理对象生命周期、对象图管理、SQL隔离、处理变更、持久化数据、数据内存优化以及数据查询等。

Core Data提供的功能繁多,但对于初学者并不十分友好,拥有陡峭的学习曲线。最近几年苹果也注意到了这个问题,通过添加PersistentContainer极大的降低了Stack创建的难度;SwiftUICore Data模版的出现让初学者也可以较轻松地在项目中使用其强大的功能了。

CloudKit

在苹果推出iCloud之后的几年中,开发者都无法将自己的应用程序同iCloud结合起来。这个问题直到2014年苹果推出了CloudKit框架后才得到解决。

CloudKit是数据库、文件存储、用户认证系统的集合服务,提供了在应用程序和iCloud容器之间的移动数据接口。用户可以在多个设备上访问保存在iCloud上的数据。

CloudKit的数据类型、内在逻辑和Core Data有很大的不同,需要做一些妥协或处理才能将两者的数据对象进行转换。事实上,当CloudKit一经推出,开发者就强烈希望两者之间能够进行便捷的转换。在推出Core Data with CloudKit之前,已经有第三方的开发者提供了将Core Data或其他数据的对象(比如realm)同步到CloudKit的解决方案,这些方案中的大多数目前仍在提供支持。

依赖于之前推出的持久化历史追踪[4]功能,苹果终于在2019年提供了自己的解决方案Core Data with CloudKit

Core Data对象 vs CloudKit对象

两个框架都有各自的基础对象类型,相互之间并不能被一一对应。在此仅对本文涉及的一些基础对象类型做简单的介绍和比较:

NSPersistentContainer vs CKContainerNSPersistentContainer通过处理托管对象模型(NSManagedObjectModel),对持久性协调器(NSPersistentStoreCoordinator)和托管对象上下文(NSManagedObjectContext)进行统一的创建和管理。开发者通过代码创建其的实例。CKContainer则和应用程序的沙盒逻辑类似,在其中可以保存结构化数据、文件等多种资源。每个使用CloudKit的应用程序应有一个属于自己的CKContainer(通过配置,一个应用程序可以对应多个CKContainer,一个CKContainer 也可以服务于多个应用程序)。开发者通常不会在代码中直接创建新的CKConttainer,一般通过iCoud控制台或在Xcode TargetSigning&Capabilities中创建。•NSPersistentStore vs CKDatabase/CkRecordZoneNSPersistentStore是所有 Core Data 持久存储的抽象基类,支持四种持久化的类型(SQLiteBinaryXMLIn-Memory)。在一个NSPersistentContainer中,通过声明多个的NSPersistentStoreDescription,可以持有多个NSPersistentStore实例(可以是不同的类型)。NSPersistentStore没有用户鉴权的概念,但可以设置只读或读写两种模式。由于Core Data with CloudKit需要持久化历史追踪[5]的支持,因此只能同步将SQLite作为存储类型的NSPersistentStore,在设备上,该NSPersistentStore的实例将指向一个SQLite数据库文件。在CloudKit上,结构化的数据存储只有一种类型,但采用了两个维度对数据进行了区分。从用户鉴权角度,CKDatabase分别提供了三种形式的数据库:私有数据库、公有数据库、共享数据库。应用程序的使用者(已经登录了iCloud账号)只能访问自己的私有数据库,该数据库的数据保存在用户个人的iCloud空间中,其他人都不可以对其数据进行操作。在公共数据库中保存的数据可以被任何授权过的应用程序调用,即使app的使用者没有登录iCloud账户,应用程序仍然可以读取其中的内容。应用程序的使用者,可以将部分数据共享给其他的同一个app的使用者,共享的数据将被放置在共享数据库中,共享者可以设置其他用户对于数据的读写权限。数据在CKDatabase中也不是以零散的方式放置在一起的,它们被放置在指定的RecoreZone中。我们可以在私有数据库中创建任意多的Zone(公共数据库和共享数据库只支持默认Zone)。当CKContainer被创建后,每种数据库中都会默认生成一个名为_defaultZoneCKRecoreZone。因此,当我们保存数据到CloudKit数据库时,不仅需要指明数据库(私有、公有、共享)类型,同时也需要标明具体的zoneID(当保存到_defaultZone时无需标记)。•NSManagedObjectModel vs SchemaNSManagedObjectModel是托管对象模型,标示着Core Data对应的数据实体(Enities)。绝大多数情况下,开发者都是使用XcodeData Model Editor来对其进行的定义,定义会被保存在xcdatamodeled文件中,其中包含了实体属性、关系、索引、约束、校验、配置等等信息。当在应用程序中启用CloudKit后,将在CKContainer创建一个SchemaSchema中包括记录类型(Record Type)、记录类型类型之间可能存在的关系、索引以及用户权限。除了直接在iCloud控制台创建Schema的内容外,也可以通过在代码中创建CKRecord,让CloudKit自动为我们创建或更新Schema中对应的内容。Schema中有权限的设定(Security Roles),可以分别为worldicloud以及creator设定不同的读写权限。•Entities vs Record Types尽管我们通常会强调Core Data不是数据库,但实体(Enitities)与数据库中的表非常相似。我们在实体中描述对象,包括其名称、属性和关系。最终将其描述成NSEntityDescription并汇总到NSManagedObjectModel中。在CloudKit中用Record Types描述数据对象的名称、属性。Enitiy中有大量的信息可以配置,但Record Types只能对应描述其中的一部分。由于两方无法一一对应,因此在设计Core Data with CloudKit的数据对象时要遵守相关规定(具体规定将在下一篇文章中探讨)。•Managed Object vs CKRecord托管对象(Managed Object)是表示持久存储记录的模型对象。托管对象是NSManagedObject或其子类的实例。托管对象在托管对象上下文(NSManagedObjectContext)中注册。在任何给定的上下文中,托管对象最多有一个实例对应于持久存储中的给定记录。在CloudKit上,每条记录被称作为CKRecord。我们不需要关心Managed ObjectIDNSMangedObjectID)的创建过程,Core Data将为我们处理一切,但对于CKRecord,多数情况下,我们需要在代码中明确为每条记录设定CKRecordIdentifier。作为CKRecord的唯一标识,CKRecordIdentifier被用于确定该CKRecord在数据库的唯一位置。如果数据保存在自定义的CKRecordZone,我们也需要在CKRecord.ID中指明。•CKSubscriptionCloudKit是云端服务,它要同一iCloud账户的不同设备(私有数据库)或者使用不同iCloud账号的设备(公共数据库)的数据变化做出相应的反馈。开发者通过CloudKitiCloud上创建CKSubscription,当CKContainer中的数据发生变化时,云端服务器会检查该变化是否满足某个CKSubscription的触发条件,在条件满足时,对订阅的设备发送远程提醒(Remote Notification)。这就是当我们在Xcode TargetSigning&Capabilities中添加上CloudKit功能时,会Xcode自动添加Remote Notification的原因。在实际使用中,需要通过CKSubscription的三个子类完成不同的订阅任务:CKQuerySubscription,当某个CKRecord满足设定的NSPercidate时推送NotificationCKDatabaseSubscription,订阅并跟踪数据库(CKDatabase)中记录的创建、修改和删除。该订阅只能用于私有数据库和共享数据库中自定义的CKRecordZone,并只会通知订阅的创建者。在以后的文章中,我们可以看到Core Data with CloudKit是如何在私有库中使用该订阅的。CKRecordZoneNotification,当用户、或者在某些情况下,CloudKit修改该区域(CKRecordZone)的记录时,记录区的订阅就会执行,例如,当记录中某个字段的值发生变化时。对于iCloud服务器推送的远程通知,应用程序需要在Application Delegate中做出响应。多数情况下,远程提醒可以采用静默通知的形式,为此开发者需要在的应用程序中启用Backgroud ModesRemote notifications

Core Data with CloudKit 的实现猜想

结合上面介绍的基础知识,让我们尝试推测一下Core Data with CloudKit的实现过程。

以私有数据库同步为例:

•初始化:1.创建CKContainer2.根据NSManagedObjectModel配置Schema3.在私有数据库中创建ID为com.apple.coredata.cloudkit.zoneCKRecordZone4.在私有数据库上创建CKDatabaseSubscription•数据导出(将本地Core Data数据导出到云端)1.NSPersistentCloudKitContainer创建后台任务响应持久化历史跟踪NSPersistentStoreRemoteChange通知2.根据NSPersistentStoreRemoteChangetransaction,将Core Data的操作转换成CloudKit的操作。比如对于新增数据,将NSManagedObject实例转换成CKRecord实例。3.通过CloudKit将转换后的CKRecord或其他CloudKit操作传递给iCloud服务器•服务器端1.按顺序处理从远端设备提交的CloudKit操作数据2.根据初始化创建的CKDatabaseSubscription检查该操作是否导致私有数据库的com.apple.coredata.cloudkit.zone中的数据发生变化3.对所有创建CKDatabaseSubscription订阅的设备(同一iCloud账户)分发远程通知•数据导入(将远程数据同步到本地)1.NSPersistentCloudKitContainer创建的后台任务响应云端的静默推送2.向云端发送刷新操作要求并附上上次操作的令牌3.云端根据每个设备的令牌,为其返回自上次刷新后数据库发生的变化4.将远端数据转换成本地数据(删除、更新、添加等)5.由于视图上下文automaticallyMergesChangesFromParen属性设置为真,本地数据的变化将自动在视图上下文中体现出来

上述步骤中省略了所有技术难点及细节,仅描述了大概的流程。

总结

本文中,我们简单介绍了关于Core DataCloudKit以及Core Data with CloudKit的一点基础知识。在下一篇文章中我们将探讨如何使用Core Data with CloudKit实现本地数据库和私有数据库的同步

PS:介绍如何使用NSPersistentContainer的文章并不少,但同其他Core Data的功能一样,用好并不容易。在两年多的使用中,我便碰到不少问题。借着今年打算在【健康笔记3】[6]中实现共享数据库功能的机会,我最近较系统地重新学习了Core Data with CloudKit并对其知识点进行了梳理。希望通过这个系列博文能让更多的开发者了解并使用Core Data with Cloudkit功能。

引用链接

[1] www.fatbobman.com: http://www.fatbobman.com [2] Apple Developer Program: https://developer.apple.com/programs/ [3] 【健康笔记】: https://www.fatbobman.com/project/healthnotes/ [4] 持久化历史追踪: https://www.fatbobman.com/posts/persistentHistoryTracking/ [5] 持久化历史追踪: https://www.fatbobman.com/posts/persistentHistoryTracking/ [6] 【健康笔记3】: https://www.fatbobman.com/project/healthnotes/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-08-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 肘子的Swift记事本 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Core Data with CloudKit (一) —— 基础
    • Core Data with CloudKit的局限性
      • Core Data with CloudKit的优点
        • Core Data
          • CloudKit
            • Core Data对象 vs CloudKit对象
              • Core Data with CloudKit 的实现猜想
                • 总结
                相关产品与服务
                数据库
                云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档