2

I am trying to use core data within my mac app with SwiftUI using Xcode 11. I have checked "Using Core Data" when creating the project. I also have created the entity (called VisitedCases) and used editor to create NSManagedObject Subclass files. I also have set the Codegen to Manual/none. Here is the code in the generated NSManagedObject files:

VisitedCases+CoreDataProperties.swift

extension VisitedCases {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<VisitedCases> {
        return NSFetchRequest<VisitedCases>(entityName: "VisitedCases")
    }

    @NSManaged public var caseNumber: String

} 

VisitedCases+CoreDataClass.swift

@objc(VisitedCases)
public class VisitedCases: NSManagedObject {

}

I called the @Environment variable and the @FetchRequest in ContentView.swift as:

struct ContentView: View {
    @Environment(\.managedObjectContext) var managedObjectContext

    @FetchRequest(entity: VisitedCases.entity(),
                  sortDescriptors: []
                  ) var orders: FetchedResults<VisitedCases>
//@State vars and the rest of the code
}

However, when I run, the app crashed as soon as launch with the following errors in the output:

2020-02-23 18:36:16.889306+0330 ImageSelector[17874:149503] [error] error: No NSEntityDescriptions in any model claim the NSManagedObject subclass 'VisitedCases' so +entity is confused.  Have you loaded your NSManagedObjectModel yet ?
CoreData: error: No NSEntityDescriptions in any model claim the NSManagedObject subclass 'VisitedCases' so +entity is confused.  Have you loaded your NSManagedObjectModel yet ?
2020-02-23 18:36:16.889389+0330 ImageSelector[17874:149503] [error] error: +[VisitedCases entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
CoreData: error: +[VisitedCases entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
2020-02-23 18:36:16.921131+0330 ImageSelector[17874:149503] executeFetchRequest:error: A fetch request must have an entity.

I also have a function that saves a string to storage and seems to work just fine:

    func addCaseNumber (caseNo: String) {
        guard caseNo != "" else {return}
        let newCaseNumber = VisitedCases(context: self.managedObjectContext)
        newCaseNumber.caseNumber = caseNo
        do {
         try self.managedObjectContext.save()
         print("Case number saved.")
        } catch {
         print(error.localizedDescription)
         }
    }

What is wrong with my code and what should I do to fix it?

MRF
  • 455
  • 1
  • 6
  • 13
  • It looks like you did not define or load your Core Data model. – Marc T. Feb 23 '20 at 16:42
  • https://stackoverflow.com/questions/53690712/no-nsentitydescriptions-in-any-model-claim-the-nsmanagedobject-subclass – lorem ipsum Feb 23 '20 at 16:52
  • @MarcT. I have checked the "Use Core Data" when creating the project so I assume that data object has been injected to the delegate etc. I also have defined the Entity in the data model and verified its name. What did I miss? – MRF Feb 23 '20 at 16:53
  • @CranialDev I have already checked that question. I couldn't switch the Codegen to Category/Extension since it would crash as well with the same error. I also didn't quite get the change from "Product.fetchRequest()" to "NSFetchRequest(entityName: "Product")" part. Where and how should this change be implemented? – MRF Feb 23 '20 at 17:06
  • That part is built into the wrapper. If you look at the CoreData documentation for FetchedResultsController you can see how it all comes together. Are you manually creating your CoreData stack? – lorem ipsum Feb 23 '20 at 17:12
  • @CranialDev I have checked box "Use Core Data" when creating the project. So the model has been created automatically. I have used Xcode editor menu to generate NSManagedObject class files. I had a look at the FetchedResultsController documentation but I do not know where to find it in my proj or how to make it. Can you elaborate more? I am amateur swift programmer please bare with me :) – MRF Feb 23 '20 at 17:20

3 Answers3

1

Try assigning your managedObjectContext in your ContentView like this

let managedObjectContext: NSManagedObjectContext =  ((UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext)!

If this works it means that your @Environment var isn't working.

To find out where the break happens start with the SceneDelegate having

let contentView = ContentView().environment(\.managedObjectContext, context)

Then see where the connection with Environment is being broken

Put something like this in all your views to see which doesn't get the Environment variable.

@Environment(\.managedObjectContext) var managedObjectContext
     var body: some View {
         print("MOC = ")
         print(managedObjectContext.name ?? "broken")
     return Text("Hello World!")
}

When you find the break reestablish it with

YourBrokenView().environment(\.managedObjectContext, managedObjectContext)
lorem ipsum
  • 21,175
  • 5
  • 24
  • 48
1

This is what worked for me I was using NSManagedObject subclases (Manual/None on the codegen definition ) for my CoreData entity cuz I was making some unwrapping. I have to delete the class and use the editor to generate again then all worked again

Misael Landeros
  • 545
  • 5
  • 18
0

In the @enviromentVAr, sometimes, you need to set the enviroment by yourself.

 let managedObjectContext: NSManagedObjectContext =  ((UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext)!

 ContentView().environment(\.managedObjectContext, managedObjectContext)

Then the managedObjectContext can work.

 @Environment(\.managedObjectContext) var managedObjectContext
E.Coms
  • 11,065
  • 2
  • 23
  • 35