2

I am fairly certain CoreData is throwing the captioned error because of the line let newGoal = Goal(context: viewContext) in function addNewGoal. But I don't know another way to "rephrase" my func.

The search results in stackoverflow of the same error seem to be irrelevant to my issue here. (one is solved by using a static var instead of lazy var; the other one is about this error occurs randomly)

Great thanks in advance

(Apologies if this is a stupid question. I am a beginner learning by building a project. CoreData is vital to the concept of my project but I am completely out of my depth and it's killing me inside. )

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 = Goal(context: 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: "Project")
        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)")
            }
        })
    }
    
    func addNewGoal() {
        let result = PersistenceController(inMemory: true)
        let viewContext = result.container.viewContext
        let newGoal = Goal(context: viewContext)
        newGoal.passed = true
        newGoal.title = "New Goal \(Date())"
        newGoal.date = Date()
    }
    
    func addNewFail() {
        let result = PersistenceController(inMemory: true)
        let viewContext = result.container.viewContext
        let newGoal = Goal(context: viewContext)
        newGoal.passed = false
        newGoal.title = "New Goal \(Date())"
        newGoal.date = Date()
    }
    
}

Error

2021-08-11 05:05:44.981041+0800 Project[27243:1370905] [error] warning: Multiple NSEntityDescriptions claim the NSManagedObject subclass 'Goal' so +entity is unable to disambiguate.
CoreData: warning: Multiple NSEntityDescriptions claim the NSManagedObject subclass 'Goal' so +entity is unable to disambiguate.

2021-08-11 05:05:44.981226+0800 Project[27243:1370905] [error] warning:      'Goal' (0x6000032cc370) from NSManagedObjectModel (0x6000026fa7b0) claims 'Goal'.
CoreData: warning:       'Goal' (0x6000032cc370) from NSManagedObjectModel (0x6000026fa7b0) claims 'Goal'.

2021-08-11 05:05:44.981343+0800 Project[27243:1370905] [error] warning:      'Goal' (0x6000032d5e40) from NSManagedObjectModel (0x6000026bc5f0) claims 'Goal'.
CoreData: warning:       'Goal' (0x6000032d5e40) from NSManagedObjectModel (0x6000026bc5f0) claims 'Goal'.

2021-08-11 05:05:44.981447+0800 Project[27243:1370905] [error] error: +[Goal entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
CoreData: error: +[Goal entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass

Edit: model file

Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
Walter Pak
  • 79
  • 7
  • One possible solution is that you need to clean the build folder in Xcode and build the project from scratch. This can sometimes happen when you change the core data model. – Joakim Danielson Aug 11 '21 at 06:41

2 Answers2

4

First, get rid of the:

let result = PersistenceController(inMemory: true)

line and make the next line:

let viewContext = container.viewContext

You already have the container variable scoped to the whole struct so it is available in the PersistenceController struct.

Your function would be this:

func addNewGoal() {
    let viewContext = container.viewContext
    let newGoal = Goal(context: viewContext)
    newGoal.passed = true
    newGoal.title = "New Goal \(Date())"
    newGoal.date = Date()
}

As to the errors, according to this answer the problem is caused having two models loaded at the same time, and by calling PersistenceController(inMemory: true) I think you may have done that.

Also, the whole point of having the shared var is so you are only using one instance of the PersistenceController. You certainly don't want to initialize it by passing inMemory: true which it is already initialized with.

Yrb
  • 8,103
  • 2
  • 14
  • 44
  • Several errors after the fix: 1. to the line `let viewContext = container.viewContext` : "instance member 'container' cannot be used on type 'PersistenceController'; did you mean to use a value of this type instead?" 2. 2 errors to the line `let newItem = Goal(context: viewContext)` : "Extra argument 'context' in call" and "Missing arguments for parameters 'entity', 'insertInto' in call" 3. (understandably) to the line `return result` : cannot find `result` in scope – Walter Pak Aug 10 '21 at 23:34
  • @WalterPak are you really using the code posted in this answer? The error messages says you are not. – Joakim Danielson Aug 11 '21 at 06:48
  • @WalterPak notice this code change is in func addNewGoal() and func addNewFail() not in the preview code. – SeaSpell Aug 11 '21 at 15:06
0

Its saying you defined a subclass of NSManaged object called Goal twice. It also says you define two models with the same class and it can't tell which one you want. Can you show your two model files?

SeaSpell
  • 678
  • 3
  • 9
  • Thank you for your reply. I added a picture of the xcdatamodel. Is that what you mean by model file(s)? I only have one of that in my project. – Walter Pak Aug 10 '21 at 23:18
  • It's saying there are two model instances. If you only have one model, it should only have one instance.. Did you generate subclasses or are you trying to make two stores somewhere? – SeaSpell Aug 11 '21 at 14:46
  • Oh ok I see what's going on. The answer above is probably the right one. I just realized your functions are inside your persistence controller struct. – SeaSpell Aug 11 '21 at 14:59