SwiftData数据同步到iCloud
SwiftData数据同步到iCloud

SwiftData数据同步到iCloud

SwiftData数据同步iCloud需要先配置iCloud容器。

配置iCloud容器

1、打开 Xcode 项目设置

在 Xcode 的项目导航中,点击项目的根目录,然后选择目标 (target) 设置。

2、进入 Signing & Capabilities

在项目设置中,点击 Signing & Capabilities 选项卡。

3、添加 iCloud 能力

点击左上方的 + Capability 按钮,搜索并选择 iCloud。这会自动为项目添加 iCloud 支持。

双击列表中的iCloud选项,将iCloud添加到项目中。

4、配置 iCloud 容器

选择添加的 iCloud 项目后,你会看到多个选项。确保勾选 CloudKit。

如果你的应用需要使用特定的容器,可以点击 Edit 按钮并选择或添加新的 iCloud 容器。

如果勾选CloudKit后,iCloud如果没有设置默认容器,则需要手动添加容器。

提示内容为:如果命名的容器不存在,Xcode 将创建一个新的容器,将其添加到 App ID,然后将新容器添加到应用程序的权利中。

这里应该使用带有“iCloud”的应用程序包 ID 前缀,例如:

iCloud.com.fangjunyu.hackingwithswift

点击“OK”按钮并创建对应的CloudKit容器。

刚开始Containers容器可能是红色,可以点击下面的刷新按钮同步,同步后颜色变为黑色。

5、新增Remote Notifications功能

再次点击Capability功能:

找到并添加Background Modes功能:

在Background Modes中勾选Remote notifications功能。

勾选该功能后,当iCloud中的数据发送变化时,应用程序就会收到通知,就可以实现本地同步。

不勾选该功能,Xcode可能会输出类似的提示:

BUG IN CLIENT OF CLOUDKIT: CloudKit push notifications require the 'remote-notification' background mode in your info plist.

告知要求CloudKit 推送通知需要信息列表中的“远程通知”后台模式。

iCloud三种不同的数据存储方式

在 iCloud 中,Key-value storage、iCloud Documents 和 CloudKit 是三种不同的数据存储方式,分别适用于不同的应用场景:

1、Key-value storage

用途:适用于保存小量、简单的用户数据,例如设置、偏好和轻量级的应用状态。

特点

提供一个键-值对(key-value pairs)的存储模型,类似于 NSUserDefaults。

数据可以在多个设备之间同步。

由于存储量小且同步速度快,适合于用户设置和状态信息(如主题、音量设置等)的跨设备同步。

示例:在 iPhone 上保存的用户设置可以通过 iCloud 同步到 iPad。

2、iCloud Documents

用途:专门用于存储用户文件和文档,例如文本文件、图片、视频等。

特点

为用户的文件提供集中存储,并能在所有设备上访问。

支持应用数据的跨设备无缝同步,但用户可以直接访问这些文件,因此适合用户文件管理的需求。

Apple 提供了 UIDocument 类来帮助管理文件,处理文件的读写和保存过程。

示例:iCloud Drive 上的文档,如 Pages、Numbers 或用户上传的 PDF 文件等。

3、CloudKit

用途:提供一个云端数据库服务,适用于保存更复杂的结构化数据,如应用的核心数据、关系型数据等。

特点

支持公有和私有数据库,可以存储大规模数据。

适合复杂数据结构,如包含关系的用户数据、共享内容、或应用的核心数据存储。

开发者可以利用 CloudKit 的 API 创建、读取、更新和删除记录。支持用户间数据共享,且具备权限控制。

示例:社交类应用的用户动态信息、跨设备的内容共享(例如笔记和提醒)、游戏的多人数据等。

使用场景对比:

Key-value storage 适合轻量级配置和偏好设置。

iCloud Documents 用于文件存储和管理,适合用户生成的内容。

CloudKit 则适合需要数据库功能的应用,能存储结构化和关联性数据,支持数据同步和复杂的应用逻辑。

查看CloudKit容器

在 Apple Developer 网站上可以查看创建的 CloudKit 容器,但这需要在 Xcode 中成功创建容器并同步后,才会出现在 Apple Developer 网站的容器列表中。

1、打开 Apple Developer 网站

访问 Apple Developer 网站 并登录开发者账户。

2、导航到 CloudKit 容器管理页面

点击顶部菜单中的账户。

在页面中,选择服务-CloudKit(英文)。

3、查看容器列表

在 CloudKit 控制台页面,点击CloudKit数据库。

这里的页面是英文,使用的是谷歌页面翻译,实际的名称为CloudKit Database。

容器名称(如 iCloud.com.fangjunyu.hackingwithswift)应该出现在列表中。

如果未看到容器,请确保在 Xcode 中正确添加了 iCloud 功能并指定了容器。

CloudKit要求

配置CloudKit容器后,需要了解CloudKit对模型有严格要求:

1、所有的属性必须有 默认值 或 可选类型。

2、所有关系也必须是 可选的。

检查创建的模型。如果之前的修复未完全满足这些要求(如遗漏了某些字段的默认值或未声明为可选类型),仍会导致 ModelContainer 初始化失败。

初始化失败截图:

会提示下面类似的报错:

Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: SwiftData.SwiftDataError(_error: SwiftData.SwiftDataError._Error.loadIssueModelContainer)

参考模型

下面是提供默认值的属性,都需要添加默认值,如果是关系则需要为可选类型:

@Model
class User {
    var name: String = "Anonymous"
    var city: String = "Unknown"
    var joinDate: Date = Date.now
    @Relationship(deleteRule: .cascade) var jobs: [Job]? = [Job]()

    init(name: String, city: String, joinDate: Date, jobs: [Job]? = nil) {
        self.name = name
        self.city = city
        self.joinDate = joinDate
        self.jobs = jobs
    }
}

我在添加默认值和可选类型过程中,因为忘记给关系添加可选类型报错,一时间还找到问题根源,因此需要注意类似的问题:

[Job]? = [Job]()

以上所有的配置完成之后,SwiftData就可以正确的同步到iCloud。

本地数据同步问题

在勾选 CloudKit 后,UserDefaults 和 URL 指向的 Documents 目录中的数据不会自动同步到 iCloud。CloudKit 和 iCloud 并不自动同步本地数据,需要特定的 API 或设置。以下是它们的存储行为与 iCloud 的关系:

1、UserDefaults

本地存储:默认情况下,UserDefaults 只在本地设备上存储数据,不会自动与 iCloud 同步。

iCloud Key-Value Storage:如果希望在 iCloud 中同步 UserDefaults 的部分数据,可以通过 NSUbiquitousKeyValueStore,它提供了键值存储(key-value storage)与 iCloud 的同步。这个功能适合简单的偏好设置和小数据量的同步。

使用 iCloud Key-Value Storage 时,需要在 Xcode 中为项目勾选 iCloud 的 Key-value storage 功能,否则数据不会同步到 iCloud。

如何使用

let iCloudStore = NSUbiquitousKeyValueStore.default

// 保存数据
iCloudStore.set("John Doe", forKey: "username")

// 读取数据
let username = iCloudStore.string(forKey: "username")
iCloudStore.synchronize()

需要注意,这种同步仅限于轻量级数据,数据量大的内容需要其他解决方案,比如 CloudKit。

2、Documents 目录中的文件(URL Documents Storage)

本地存储:通常存储在 Documents 或 Library 中的文件,默认也不会自动同步到 iCloud。

iCloud Drive 手动存储:如果你希望将某些文件同步到 iCloud,开发者需要主动将文件存储到 iCloud Drive 目录下(例如在 Documents 目录中创建一个 iCloud 目录并将文件写入)。

FileManager 的 url(forUbiquityContainerIdentifier:) 方法用于访问 iCloud Documents 功能的存储路径。将文件写入这个路径可以实现文件的 iCloud 同步,但这需要在 Xcode 中启用 iCloud Documents 功能

使用方式

let iCloudURL = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents").appendingPathComponent("yourFileName")
// 将文件写入到 iCloudURL 指定的位置

总结

以上是SwiftData数据同步到iCloud的全部知识,主要涉及的知识点为:

  1. Xcode项目配置;
  2. iCloud三种数据存储方式的介绍
  3. 从网页中查看CloudKit容器
  4. CloudKit对模型的要求
  5. 以及本地数据同步的问题

实际上,我并没有测试UserDefaults和Documents本地文件同步iCloud的步骤,可能需要等待后面开发具体应用时,涉及到这方面知识点,再进一步完善本文。

需要注意的是,SwiftData同步iCloud后,会出现很多迷之错误,没有具体的报错描述,只会给你一个报错。例如你的模型没有按照CloudKit要求,有一个字段没有赋值或者关系没有设置可选类型,运行Xcode时就会有报错,而且不会给你提醒,必须要自己找。

所以,一切都要自己努力,学习和了解Apple新推出的这一存储功能。

补充知识

NSUbiquitousKeyValueStore是什么?

NSUbiquitousKeyValueStore 是 Apple 提供的 iCloud 功能,用于在轻量级应用数据(如用户偏好设置、配置或状态)在启用 iCloud 的 Apple 设备之间进行同步。它不是 SwiftUI 的特有功能,而是 Foundation 框架的一部分,可以在 Swift 和 Objective-C 中使用。

什么是 NSUbiquitousKeyValueStore?

iCloud 的轻量级键值存储:主要用于存储小型数据,例如用户设置、应用配置等。每个应用的总存储空间有限(当前约 1 MB),适合频繁更新但体量小的数据。

跨设备同步:存储的数据会自动通过 iCloud 同步到用户的其他 Apple 设备。只要用户在设备上登录同一个 Apple ID 并开启 iCloud,数据就会保持一致。

NSUbiquitousKeyValueStore 的工作方式

本地与 iCloud 数据的同步:数据存入 NSUbiquitousKeyValueStore 后,会自动同步到 iCloud,在其他设备上也能读取和使用。

手动同步:可以通过 synchronize() 方法手动触发数据同步,确保最新数据上传到 iCloud 或从 iCloud 下载更新。

基本用法

在 Swift 中使用时,我们首先要访问默认的 NSUbiquitousKeyValueStore 实例,然后存储或读取数据:

let iCloudStore = NSUbiquitousKeyValueStore.default

// 保存数据
iCloudStore.set("John Doe", forKey: "username")

// 读取数据
let username = iCloudStore.string(forKey: "username")

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注