我遵循与“在CloudKit中使用核心数据”中的相同步骤:
我想念什么?
我正在开发一个用于NSPersistentCloudKitContainer在设备之间共享数据的应用程序。核心数据模型有多个实体,其中两个实体通过与其各自逆的关系连接。我遇到的问题是,当我设置与nil云数据的关系时未更新,并且当我重新启动应用程序时,该关系会重置回设置为nil.
这是新版本中的错误NSPersistentCloudKitContainer吗?还有其他人有这个问题吗?
我用来CloudKit存储公开可用的数据,并将新数据NSPersistentCloudKitContainer作为我的核心数据堆栈的一部分来存储/同步私有数据。
当用户打开我的应用程序时,他们处于以下 4 种状态之一:
状态 1 和状态 2 代表我的快乐路径。如果他们是新用户,我想在显示初始视图之前向用户的私人存储添加一些数据。如果他们是回头客,我想从核心数据中获取数据以传递到初始视图。
确定新/老用户:
我的计划是使用NSUbiquitousKeyValueStore. 我对此的担忧是处理以下情况:
下载应用程序 -> 被记录为之前启动过该应用程序 -> 删除并在新设备上重新安装/安装该应用程序
我认为NSUbiquitousKeyValueStore需要一些时间才能接收更新,因此我需要等待其完成同步,然后再进入初始视图。那么问题来了,如果他们无法访问 iCloud 会发生什么?NSUbiquitousKeyValueStore如果无法收到更新,如何告诉我他们是否是回访用户?
确定 iCloud 访问:
根据我所做的研究,我可以检查iCloudFileManager.default.ubiquityIdentityToken是否nil可用,但这不会告诉我原因。我必须用它CKContainer.default().accountStatus来了解为什么 iCloud 不可用。问题是这是一个异步调用,我的应用程序在了解他们的帐户状态是什么之前就会继续前进。
我对这个实在是摸不着头脑。优雅地确保所有这些状态都得到处理的最佳方法是什么?
core-data ios nsubiquitouskeyvaluestore cloudkit nspersistentcloudkitcontainer
我有一个用于NSPersistentCloudKitContainer与 iCloud 同步数据的应用程序。用户报告偶尔数据丢失,之后我开始调试我的实现。
我的应用程序实现的一部分是显示一个弹出窗口,其中显示信息并有一个确认按钮。当用户单击此按钮时,自定义NSManagedObject子类的一个或多个实例将被修改。
同时,NSPersistentCloudKitContainer在应用程序退出并激活时触发镜像过程。当用户单击上述确认按钮时会发生这种情况。它通过执行NSCloudKitMirroringExportRequest和NSCloudKitMirroringImportRequest请求来做到这一点。
换句话说,在我的应用程序中,数据同时被修改(通过代码显式)和镜像(通过 CloudKit 隐式),这就是出错的地方。
本质上是这样的:
NSTimeInterval实例的属性 ( )NSManagedObject增加(例如 0 + 1 = 1)。NSPersistentCloudKitContainer 当应用程序激活或退出时隐式开始镜像数据。在这个阶段,我希望属性的值与最新的(本地)更改相匹配(因此在我的示例 2 中)。但相反,它匹配初始增量(因此在我的示例 1 中),覆盖我最新的(本地)更改导致数据丢失。显然,NSCloudKitMirroringImportRequest恢复到镜像进程启动时的状态,这也可以在日志中看到:
CoreData: debug: CoreData+CloudKit: -[PFCloudKitImporterZoneChangedWorkItem applyAccumulatedChanges:error:]
[…]
Importing updated records:
(
"<CKRecord: 0x10225b560; recordID=5458F9C8-7BE2-4563-92DE-650ED4C643F5:(com.apple.coredata.cloudkit.zone:__defaultOwner__), recordChangeTag=23, values={\n \"CD_activity\" = \"3E497A4C-6467-48F4-B7F4-6F1B2B7BC779\";\n \"CD_date\" = \"2020-04-26 07:28:00 +0000\";\n \"CD_duration\" = \"1\";\n \"CD_entityName\" = Mutation;\n}, recordType=CD_Mutation>"
)
Run Code Online (Sandbox Code Playgroud)
在这个阶段,我不确定这是否是NSPersistentCloudKitContainer …
macos nsmanagedobject swift cloudkit nspersistentcloudkitcontainer
我正在尝试配置 CoreData+CloudKit 以NSPersistentCloudKitContainer自动将数据同步到 CloudKit 或从 CloudKit 同步数据。
按照Apple 指南,设置一个实体、在 Xcode 中添加适当的功能、在我的 AppDelegate 中设置persistentContainer和就足够简单了。saveContext
我通过 拨打fetch()和save()拨打电话NSManagedObjectContext,并且能够毫无问题地保存和获取记录。我可以在 CloudKit 仪表板中看到它们。
但是,如果我从模拟器中卸载应用程序并重建/重新安装,我的应用程序fetchRequest(没有排序NSPredicate或排序,只是获取所有记录)始终返回一个空列表。我使用相同的 iCloud 帐户,并且尝试了公共和私有数据库范围。如果我创建一条新记录,然后重试我的提取请求,我可以检索该新创建的记录,但永远不会检索任何旧记录。我 100% 确定这些记录仍在 CloudKit 数据库中,因为我可以在 CloudKit Dashboard Web 应用程序上看到它们。
我查看了Apple 的 CoreDataCloudKitDemo应用程序,它能够在卸载/重新安装后从 CloudKit 数据库中获取“Post”实体,所以我知道这是可能的。但是,它使用的是NSFetchedResultsController,这不适用于我的应用程序(我的应用程序是 SpriteKit 游戏)。
我尝试将 CoreData+Cloudkit 代码复制到一个全新的 Xcode 项目中,我可以在那里重现此问题。这是我的代码供参考:
import UIKit
import CoreData
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
lazy var persistentContainer: NSPersistentContainer = {
// Create a …Run Code Online (Sandbox Code Playgroud) 我在 iOS15 beta 4 上使用 NSPersistentCloudKitContainer 来跨设备同步核心数据。在设备上启动并登录 iCloud 时,我在日志中收到以下错误:
<NSCloudKitMirroringResult:0x28167ae60>成功:0 madeChanges:0错误:<CKError 0x2818a94d0:“帐户暂时不可用”(1028/2011);“由于身份验证令牌错误或丢失,帐户暂时不可用”>
我有以下代码:
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "AppName")
if inMemory {
let storeDescription = NSPersistentStoreDescription(url: URL(fileURLWithPath: "/dev/null"))
container.persistentStoreDescriptions = [storeDescription]
} else {
let storeURL = URL.storeURL(for: "my.app.group", databaseName: "AppName")
let storeDescription = NSPersistentStoreDescription(url: storeURL)
storeDescription.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: "iCloud.my.app")
container.persistentStoreDescriptions = [storeDescription]
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
}
Run Code Online (Sandbox Code Playgroud) 我在应用程序商店中有一个应用程序,我正在进行轻量级迁移(添加新属性和新实体,而不是删除任何内容)。通过广泛的研究,我知道我需要为本地版本的数据模型添加当前核心数据模型的新版本。任何更新应用程序且仅使用本地数据的人都会自动迁移。
但是,我无法找到有关更新 iCloud 架构(来自 icloud.developer.apple.com)时发生的情况的任何信息。主要是,我担心使用旧版本应用程序并使用 iCloud 的用户。当我更新 iCloud 网站中的架构时,旧版本应用程序上的用户是否会丢失当前数据或无法同步其数据,因为他们的本地架构与 iCloud 架构不同?
另外,我正在使用NSPersistentCloudKitContainerCloudKit 来同步核心数据。
非常感谢任何帮助,因为我不想弄乱任何人的数据!
core-data core-data-migration icloud cloudkit nspersistentcloudkitcontainer
我正在构建一个使用NSPersistentCloudKitContainer. 该应用程序没有共享功能,其唯一的后端功能是使用 cloudkit 容器在用户设备之间同步数据。设置相当简单,实例化容器,设置单个商店描述,然后加载商店。
我的大问题:我需要对持久历史记录进行任何操作吗?我尚未找到这个问题的具体答案,但据我所知,持久历史记录跟踪用于将一个目标(例如扩展)中发生的更改合并到另一个目标中。听起来我不需要它来充分利用 iCloud 同步。
在开发过程中,我已经转向NSPersistentCloudKitContainer并开始了尝试测试尽可能多的场景以确保没有人丢失任何数据的可怕过程。
在一些测试中我看到了这样的错误:
<CKError 0x28033a310: "Partial Failure" (2/1011); "Failed to modify some records"; uuid = B6015357-50E0-40B3-949F-1557F59A23DB; container ID = "iCloud.com.xxxx.yyyyyy"; partial errors: {
F023EFDF-B9DE-4C17-872B-01C34C0DF129:(com.apple.coredata.cloudkit.zone:__defaultOwner__) = <CKError 0x280266fa0: "Invalid Arguments" (12/2006); server message = "Cannot create or modify field 'CD_someField' in record 'CD_someRecord' in production schema"; uuid = B6015357-50E0-40B3-949F-1557F59A23DB>
... 399 "Batch Request Failed" CKError's omited ...
}>
Run Code Online (Sandbox Code Playgroud)
我能够修复这个问题,但它只会影响某些场景,如果这种情况发生在真正的用户身上,他们(和我)将永远不会知道这个问题,并且他们的数据也不会同步到 CloudKit。
如果商店无法加载,您会收到一个错误,但如果它加载但不同步,则不会。
所以我的问题是:有没有办法接收代码中的此类错误?
我寻找了通知和委托方法,但找不到。
我发现.NSPersistentStoreRemoteChange通知被多次收到,有时多达 10 次。
我认为这没有害处,但最好的情况是它会耗尽处理能力。
\n所以我的问题是:
\n--
\n我有以下代码来设置我的容器。它包含在单例的初始化程序中,我已经确认它被调用一次。
\nguard let modelURL = Bundle(for: type(of: self)).url(forResource: momdName, withExtension:"momd"),\n let mom = NSManagedObjectModel(contentsOf: modelURL)\n else {\n fatalError(" Error loading model from bundle")\n }\n \n let containerURL = folderToStoreDatabaseIn.appendingPathComponent("Model.sqlite")\n \n container = NSPersistentCloudKitContainer(name: momdName, managedObjectModel: mom)\n \n guard let description = container.persistentStoreDescriptions.first else {\n fatalError(" ###\\(#function): Failed to retrieve a persistent store description.")\n }\n \n description.url = …Run Code Online (Sandbox Code Playgroud)