[SOLVED ]Multiple NSEntityDescriptions claim the NSManagedObject subclass so +entity is unable to disambiguate

Viewed 51

I am making simple app, that tracks calories. It stores data in simple CoreData model. This is my code responsible for creating the data model.

It's simple and it's based on the code generated by 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)
    }
}

My DataModel looks like this: enter image description here

While trying to add a meal I get this warning from 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.

The warning finally results with error:

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

Of course apart from the warning and CoreData error my implementation is working and data are correctly saved.

The error and warning only shows up when I try to add new meal.

Worth mentioning is, that the warning and error don't occur when I'm modifying existing entry or deleting it.

So the above functions: addFood and save are responsible for adding and saving the data.

Here's the code, that is supposed to invoke above functions:

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()
    }
}

Thanks to @TomHarrington question is now solved. All credit goes to him.

I've been creating new instance of PersistanceController every time I was adding new meal to the CoreData.

The solution is to access the instance through immutable variable static let shared.

The working code in AddFoodView is then:

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