Core Data 首次启动时将数据保存到错误的数据库中

Posted

技术标签:

【中文标题】Core Data 首次启动时将数据保存到错误的数据库中【英文标题】:Core Data saves data into the wrong database at first start 【发布时间】:2017-05-04 15:07:09 【问题描述】:

我有一个具有两种配置的 DataModel。一个用于预加载数据,另一个用于用户数据。 首次启动时,预加载 SQLLite 数据库被复制到 Documents 文件夹。用户数据数据库由 Core Data 在 ApplicationSupport Directory 中创建。到目前为止一切正常。但是现在的问题是:如果是第一次启动,即使调用了 saveContext() 方法,也没有保存任何内容。在下一次应用启动时,所有用户数据都将消失。但这不是第一次启动,一切正常,所有用户数据在下一次应用启动时都在那里。有谁知道问题是什么?这是我的核心数据堆栈:

    lazy var persistentContainer: NSPersistentContainer = 
        let container = NSPersistentContainer(name: "CoreData_App")

        container.persistentStoreDescriptions[0].configuration = "PreloadData"
        container.persistentStoreDescriptions[0].url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("PreloadData.sqlite")

        let userStoreDescription = NSPersistentStoreDescription(url: FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!.appendingPathComponent("UserData.sqlite"))
        userStoreDescription.configuration = "UserData"

        container.persistentStoreDescriptions.append(userStoreDescription)


        container.loadPersistentStores(completionHandler:  (storeDescription, error) in
            if let error = error as NSError? 
                fatalError("Unresolved error \(error), \(error.userInfo)")
            
        )
        return container
    ()

    // MARK: - Core Data Saving support

    func saveContext () 
        let context = persistentContainer.viewContext
        if context.hasChanges 
            do 
                try context.save()
             catch 
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            
        
    

编辑 经过大量测试,我发现数据在第一次启动时存储在预加载数据库中,在第二次启动时正确存储在用户数据数据库中。但我也想在用户数据库的第一次启动时保存数据。这里是我保存数据的代码:

@IBAction func pressedFavoriteButton(_ sender: UIButton) 
        if userRating == nil 
            let rating = UserRating(context: DataController.sharedInstance.persistentContainer.viewContext)
            rating.entryID = (entry?.id)!
            userRating = rating
        

        apiHandler.sendRequest(.POST)  (response, error) in
            if let error = error 
                print(error.localizedDescription)
                return
            
            DispatchQueue.main.async 
                self.userRating?.isFavorite = !self.favoriteButton.isSelected
                self.favoriteButton.isSelected = !self.favoriteButton.isSelected
                
               DataController.sharedInstance.saveContext()
            
        
    

【问题讨论】:

您必须不正确地初始化核心数据堆栈。请分享您的代码。 我不知道问题出在哪里,所以很难知道我应该分享什么。但我现在已经将我的核心数据堆栈的代码添加到问题中。 您的项目中使用了哪个版本的 Swift? 它使用 Swift 3 你是递归保存到数据库吗? 【参考方案1】:

首先让我们正确设置商店,

let preloadDataStoreDescription = NSPersistentStoreDescription(url: FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("PreloadData.sqlite"))

let userStoreDescription = NSPersistentStoreDescription(url: FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!.appendingPathComponent("UserData.sqlite"))

    userStoreDescription.configuration = "UserData"
preloadDataStoreDescription.configuration = "PreloadData"

container.persistentStoreDescriptions = [preloadDataStoreDescription, userStoreDescription]

由于您有 2 个数据库,这取决于您存储的实体。

如果实体属于预加载配置,它将存储在预加载数据库中,否则将存储在用户数据库中。

附: 您还可以使用标志进一步调试

-com.apple.CoreData.SQLDebug 1

在 Edit Scheme > Arguments > Arguments Passed on launch

另外,如果不是真的需要,我建议不要使用 2 个数据库使设计复杂化。

【讨论】:

感谢您提供更好的设置代码。是的,我知道配置是如何工作的,但问题是它在第一次启动时将所有数据存储在预加载数据库中(以及不在预加载配置中的实体)。第一次启动后一切正常。 我已尝试查看您的问题以及您提供的详细信息。它应该按照您描述的方式运行。尝试将不属于它的实体存储在数据库中会导致异常。

以上是关于Core Data 首次启动时将数据保存到错误的数据库中的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SQLite 文件预加载 Core Data,该文件引用使用“外部存储”保存的图像?

如何将 NSMutable 数组中的数据存储在 Core Data 中?

保存在 Core Data 中的 iOS 数据在启动后无法保存

在 EF Core/自动生成 ID 中保存实体时将 IT 留空

Core Data 默认使用线程吗?

Core Data 对象有时不会保存到永久存储中