【问题标题】:[SOLVED ]Multiple NSEntityDescriptions claim the NSManagedObject subclass so +entity is unable to disambiguate[已解决]多个 NSEntityDescriptions 声明了 NSManagedObject 子类,因此 +entity 无法消除歧义
【发布时间】:2022-12-31 03:41:00
【问题描述】:

我正在制作简单的应用程序,用于跟踪卡路里。它将数据存储在简单的 CoreData 模型中。 这是我负责创建数据模型的代码。

它很简单,并且基于 Xcode 生成的代码。

import Foundation
import CoreData

class PersistenceController: ObservableObject {
    static let shared = PersistenceController()

    static var preview: PersistenceController = {
        let result = PersistenceController(inMemory: true)
        let viewContext = result.container.viewContext
        do {
            try viewContext.save()
        } catch {
            let nsError = error as NSError
            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
        }
        return result
    }()

    let container: NSPersistentContainer
    
    init(inMemory: Bool = false) {
        container = NSPersistentContainer(name: "FoodModel")
        if inMemory {
            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
        }
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        container.viewContext.automaticallyMergesChangesFromParent = true
    }
    
    func save(context: NSManagedObjectContext) {
        do {
            try context.save()
            print("Data has been saved successfully.")
        } catch {
            // Handle errors in our database
            let nsError = error as NSError
            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
        }
    }
    
    func addFood(name: String, calories: Double, context: NSManagedObjectContext) {
        let food = Food(context: context)
        food.id = UUID()
        food.date = Date()
        food.name = name
        food.calories = calories
        
        save(context: context)
    }
    
    func editFood(food: Food, name: String, calories: Double, context: NSManagedObjectContext) {
        food.date = Date()
        food.name = name
        food.calories = calories
        
        save(context: context)
    }
}

我的数据模型如下所示:

在尝试加餐时,我从 CoreData 收到此警告:

2022-09-06 17:52:24.248483+0200 TrackCalories[67203:10277525] [error] warning: Multiple NSEntityDescriptions claim the NSManagedObject subclass 'TrackCalories.Food' so +entity is unable to disambiguate.

警告最终导致错误:

CoreData: error: +[TrackCalories.Food entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass

当然,除了警告和 CoreData 错误之外,我的实现工作正常并且数据已正确保存。

错误和警告仅在我尝试添加新餐时出现。

值得一提的是,当我修改现有条目或删除它时,不会出现警告和错误。

所以上面的函数:addFood和save负责数据的添加和保存。

这是应该调用上述函数的代码:

struct AddFoodView: View {
    @Environment(\.managedObjectContext) var managedObjContext
    @Environment(\.dismiss) var dismiss
    
    @State private var name = ""
    @State private var calories: Double = 0

    
    var body: some View {
            Form {
                Section() {
                    TextField("What have you eaten?", text: $name)
                    
                    VStack {
                        Text("Calories: \(Int(calories))")
                        Slider(value: $calories, in: 0...2000, step: 10)

                    }
                    .padding()
                    
                    HStack {
                        Spacer()
                        Button("Add meal") {
                            PersistenceController().addFood(
                                name: name,
                                calories: calories,
                                context: managedObjContext)
                            dismiss()
                        }
                        Spacer()
                    }
                }
        }
    }
}

struct AddFoodView_Previews: PreviewProvider {
    static var previews: some View {
        AddFoodView()
    }
}

感谢@TomHarrington 问题现在已经解决了。所有的功劳都归于他。

每次我向 CoreData 添加新餐时,我都在创建 PersistanceController 的新实例。

解决方案是通过不可变变量static let shared来访问实例。

AddFoodView 中的工作代码是:

PersistenceController.shared.addFood(
                                name: name,
                                calories: calories,
                                context: managedObjContext)
                            dismiss()
                        }

【问题讨论】:

  • 清理构建文件夹,看看是否有帮助。
  • 感谢@JoakimDanielson 的建议,不幸的是,我在删除派生数据之前曾尝试清理它。它没有帮助:/
  • 也许您可以共享保存新对象的代码
  • 你有没有可能不小心创建了多个PersistenceController
  • @RalphL 我不是 SwiftUI 专家,但看起来每次单击“加餐”按钮时,都会创建一个新的 PersistenceController。这可能是个坏主意。

标签: core-data swiftui


【解决方案1】:

当我尝试编写单元测试时,我的 SwiftUI 应用程序也遇到了这个问题。这是最终对我有用的代码

final class SampleTests: XCTestCase {
    var viewContext: NSManagedObjectContext?
    
    override func setUpWithError() throws {
        viewContext = PersistenceController.preview.container.viewContext
        try? viewContext!.save()
    }
    override func tearDownWithError() throws {
        viewContext!.reset()
    }
    func testSomething() throws { ... }
}

请注意,viewContext 必须是可选的(因此需要展开),因为我们没有覆盖 init()

【讨论】:

    猜你喜欢
    • 2019-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 2015-04-28
    相关资源
    最近更新 更多