【发布时间】:2022-10-02 11:23:08
【问题描述】:
我在 XCode 中创建了一个空白 SwiftUI 项目,并选择包含 Core Data 和 Cloud Kit。
默认情况下,Apple 已经在项目中包含了一些 Core Data 示例代码和实体,还有一个包含 NSPersistentCloudKitContainer 代码的 Persistence.swift 文件。
(Core Data 的示例代码是将时间戳记录到 SwiftUI 列表中,例如 Apple 介绍视频的 05:18~06:10:https://developer.apple.com/videos/play/wwdc2019/202/)
经过一些基本设置后,假设应用程序的数据记录和记录类型可以显示在 Cloud Kit 仪表板的相关容器上,但它没有。
这是我所做的:
- 我按照教程https://developer.apple.com/documentation/coredata/mirroring_a_core_data_store_with_cloudkit/setting_up_core_data_with_cloudkit
- 使用 Core Data 和 Cloud Kit 创建项目
- 由于 Apple 已经设置了 Persistence.swift 文件,因此没有触及任何代码。
- 还没有触及应用结构、内容视图和核心数据实体(保持所有示例代码不变)
- 已选择自动管理签名和开发团队,并带有付费开发人员帐户。
- 添加了 iCloud 功能
- 在 iCloud 功能中选择 CloudKit,创建 CloudKit 容器。
- 添加了后台模式功能并选择了远程通知。
接着:
- 启动模拟器,启动应用程序,被要求使用 Apple ID 登录,然后就这样做了。
- 在 SwiftUI 列表中添加一些时间戳。
- 杀死应用程序并重新启动,时间戳仍然存在,甚至删除应用程序并重新安装。 Core Data 示例代码完美运行。
- 进入CloudKit Dashboard的相关容器,选择Records,Private Database,Record Type只有\"Users\"。没有显示其他记录类型。
日志
CoreData: debug: CoreData+CloudKit: -[PFCloudKitOptionsValidator validateOptions:andStoreOptions:error:](36): Validating options: <NSCloudKitMirroringDelegateOptions: 0x600003fd45a0> containerIdentifier:iCloud.com.ProjectName databaseScope:Private ckAssetThresholdBytes:<null> operationMemoryThresholdBytes:<null> useEncryptedStorage:NO useDeviceToDeviceEncryption:NO automaticallyDownloadFileBackedFutures:NO automaticallyScheduleImportAndExportOperations:YES skipCloudKitSetup:NO preserveLegacyRecordMetadataBehavior:NO useDaemon:YES apsConnectionMachServiceName:<null> containerProvider:<PFCloudKitContainerProvider: 0x600000fdc150> storeMonitorProvider:<PFCloudKitStoreMonitorProvider: 0x600000fdc1b0> metricsClient:<PFCloudKitMetricsClient: 0x600000fdc1f0> metadataPurger:<PFCloudKitMetadataPurger: 0x600000fdc200> scheduler:<null> notificationListener:<null> containerOptions:<null> defaultOperationConfiguration:<null> progressProvider:<NSPersistentCloudKitContainer: 0x6000018cd340> test_useLegacySavePolicy:YES archivingUtilities:<PFCloudKitArchivingUtilities: 0x600000fdc210>
storeOptions: {
NSInferMappingModelAutomaticallyOption = 1;
NSMigratePersistentStoresAutomaticallyOption = 1;
NSPersistentCloudKitContainerOptionsKey = \"<NSPersistentCloudKitContainerOptions: 0x6000003a4000>\";
NSPersistentHistoryTrackingKey = 1;
NSPersistentStoreMirroringOptionsKey = {
NSPersistentStoreMirroringDelegateOptionKey = \"<NSCloudKitMirroringDelegate: 0x6000036d0340>\";
};
}
CoreData: debug: CoreData+CloudKit: -[NSCloudKitMirroringDelegate observeChangesForStore:inPersistentStoreCoordinator:](385): <NSCloudKitMirroringDelegate: 0x6000036d0340>: Observing store: <NSSQLCore: 0x14d504650> (URL: file:///ADDRESS/PROJECT.sqlite)
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _setUpCloudKitIntegration](530): <NSCloudKitMirroringDelegate: 0x6000036d0340>: Successfully enqueued setup request.
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate checkAndExecuteNextRequest](2928): <NSCloudKitMirroringDelegate: 0x6000036d0340>: Checking for pending requests.
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate checkAndExecuteNextRequest]_block_invoke(2941): <NSCloudKitMirroringDelegate: 0x6000036d0340>: Executing: <NSCloudKitMirroringDelegateSetupRequest: 0x600001885e40> C5E6C108-29AD-4B29-B2F2-2E7B6CF17C43
CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](446): Skipping migration for \'ANSCKDATABASEMETADATA\' because it already has a column named \'ZLASTFETCHDATE\'
CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](503): Skipping migration for \'ANSCKMETADATAENTRY\' because it already has a column named \'ZDATEVALUE\'
CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](446): Skipping migration for \'ANSCKRECORDZONEMETADATA\' because it already has a column named \'ZLASTFETCHDATE\'
CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](462): Skipping migration for \'ANSCKRECORDZONEMETADATA\' because it already has a column named \'ZSUPPORTSFETCHCHANGES\'
CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](462): Skipping migration for \'ANSCKRECORDZONEMETADATA\' because it already has a column named \'ZSUPPORTSATOMICCHANGES\'
CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](462): Skipping migration for \'ANSCKRECORDZONEMETADATA\' because it already has a column named \'ZSUPPORTSRECORDSHARING\'
CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](462): Skipping migration for \'ANSCKRECORDZONEMETADATA\' because it already has a column named \'ZSUPPORTSZONESHARING\'
CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](479): Skipping migration for \'ANSCKRECORDZONEMETADATA\' because it already has a column named \'ZNEEDSIMPORT\'
CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](479): Skipping migration for \'ANSCKRECORDZONEMETADATA\' because it already has a column named \'ZNEEDSRECOVERYFROMZONEDELETE\'
CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](479): Skipping migration for \'ANSCKRECORDZONEMETADATA\' because it already has a column named \'ZNEEDSRECOVERYFROMUSERPURGE\'
CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](479): Skipping migration for \'ANSCKRECORDZONEMETADATA\' because it already has a column named \'ZENCODEDSHAREDATA\'
CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](479): Skipping migration for \'ANSCKRECORDZONEMETADATA\' because it already has a column named \'ZNEEDSSHAREUPDATE\'
CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](479): Skipping migration for \'ANSCKRECORDZONEMETADATA\' because it already has a column named \'ZNEEDSSHAREDELETE\'
CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](479): Skipping migration for \'ANSCKRECORDZONEMETADATA\' because it already has a column named \'ZNEEDSRECOVERYFROMIDENTITYLOSS\'
CoreData: CloudKit: CoreData+CloudKit: -[PFCloudKitSetupAssistant _checkUserIdentity:]_block_invoke(1235): <PFCloudKitSetupAssistant: 0x6000029c2880>: CKIdentity record matches store: <CKRecordID: 0x600000dab560; recordName=_8b74d2123c870a6cd2fb07b5c74bb4b1, zoneID=_defaultZone:__defaultOwner__>
2022-09-25 11:06:51.874997+0800 ProjectName[19841:1140864] [error] error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _performSetupRequest:]_block_invoke(1106): <NSCloudKitMirroringDelegate: 0x6000036d0340>: Failed to set up CloudKit integration for store: <NSSQLCore: 0x14d504650> (URL: file:///ADDRESS/ProjectName.sqlite)
<CKError 0x600000349440: \"Partial Failure\" (2/1011); \"Failed to modify some record zones\"; partial errors: {
com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x6000003b0390: \"Internal Error\" (1/5000); \"Failed to sync user keys\">
}>
CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _performSetupRequest:]_block_invoke(1106): <NSCloudKitMirroringDelegate: 0x6000036d0340>: Failed to set up CloudKit integration for store: <NSSQLCore: 0x14d504650> (URL: file:///ADDRESS/PROJECT.sqlite)
<CKError 0x600000349440: \"Partial Failure\" (2/1011); \"Failed to modify some record zones\"; partial errors: {
com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x6000003b0390: \"Internal Error\" (1/5000); \"Failed to sync user keys\">
}>
2022-09-25 11:06:51.875077+0800 ProjectName[19841:1140864] [error] error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate recoverFromError:](2115): <NSCloudKitMirroringDelegate: 0x6000036d0340> - Attempting recovery from error: <CKError 0x600000349440: \"Partial Failure\" (2/1011); \"Failed to modify some record zones\"; partial errors: {
com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x6000003b0390: \"Internal Error\" (1/5000); \"Failed to sync user keys\">
}>
CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate recoverFromError:](2115): <NSCloudKitMirroringDelegate: 0x6000036d0340> - Attempting recovery from error: <CKError 0x600000349440: \"Partial Failure\" (2/1011); \"Failed to modify some record zones\"; partial errors: {
com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x6000003b0390: \"Internal Error\" (1/5000); \"Failed to sync user keys\">
}>
2022-09-25 11:06:51.875317+0800 ProjectName[19841:1140864] [error] error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _recoverFromPartialError:forStore:inMonitor:]_block_invoke(2464): <NSCloudKitMirroringDelegate: 0x6000036d0340>: Found unknown error as part of a partial failure: <CKError 0x6000003b0390: \"Internal Error\" (1/5000); \"Failed to sync user keys\">
CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _recoverFromPartialError:forStore:inMonitor:]_block_invoke(2464): <NSCloudKitMirroringDelegate: 0x6000036d0340>: Found unknown error as part of a partial failure: <CKError 0x6000003b0390: \"Internal Error\" (1/5000); \"Failed to sync user keys\">
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _finishedRequest:withResult:](2959): Finished request: <NSCloudKitMirroringDelegateSetupRequest: 0x600001885e40> C5E6C108-29AD-4B29-B2F2-2E7B6CF17C43 with result: <NSCloudKitMirroringResult: 0x600000d8e7e0> success: 0 madeChanges: 0 error: <CKError 0x600000349440: \"Partial Failure\" (2/1011); \"Failed to modify some record zones\"; partial errors: {
com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x6000003b0390: \"Internal Error\" (1/5000); \"Failed to sync user keys\">
}>
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate checkAndExecuteNextRequest](2928): <NSCloudKitMirroringDelegate: 0x6000036d0340>: Checking for pending requests.
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate checkAndExecuteNextRequest]_block_invoke(2944): <NSCloudKitMirroringDelegate: 0x6000036d0340>: No more requests to execute.
来自 Apple 的持久容器结构代码以防万一
import CoreData
struct PersistenceController {
static let shared = PersistenceController()
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
for _ in 0..<10 {
let newItem = Item(context: viewContext)
newItem.timestamp = Date()
}
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError(\"Unresolved error \\(nsError), \\(nsError.userInfo)\")
}
return result
}()
let container: NSPersistentCloudKitContainer
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: \"ProjectName\")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: \"/dev/null\")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError(\"Unresolved error \\(error), \\(error.userInfo)\")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
}
}
标签: ios core-data swiftui cloudkit nspersistentcloudkitcontainer