NSPersistentDocument FetchRequest warp property crash on macOS Document App SwiftUI project

248 Views Asked by At
  1. Project create usinging Xcode macOS Document App template, with Use Core Data checkbox checked.
  2. Add a Book entity to Document.xcdatamodeld
  3. Add FetchRequest warp property to ContentView,
@FetchRequest(entity: Book.entity(), sortDescriptors: []) var books: FetchedResults<Book>
  1. Build and Run, Crash!

Crash log from console is

2020-07-03 23:12:23.597880+0800 DocMacDemo[15236:4376209] [error] error: No NSEntityDescriptions in any model claim the NSManagedObject subclass 'DocMacDemo.Book' so +entity is confused.  Have you loaded your NSManagedObjectModel yet ?
CoreData: error: No NSEntityDescriptions in any model claim the NSManagedObject subclass 'DocMacDemo.Book' so +entity is confused.  Have you loaded your NSManagedObjectModel yet ?
2020-07-03 23:12:23.598287+0800 DocMacDemo[15236:4376209] [error] error: +[DocMacDemo.Book entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
CoreData: error: +[DocMacDemo.Book entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
2020-07-03 23:12:23.644491+0800 DocMacDemo[15236:4376209] executeFetchRequest:error: A fetch request must have an entity.
2020-07-03 23:12:23.653769+0800 DocMacDemo[15236:4376209] [error] error: The fetch request's entity 0x600003500420 'Book' appears to be from a different NSManagedObjectModel than this context's
CoreData: error: The fetch request's entity 0x600003500420 'Book' appears to be from a different NSManagedObjectModel than this context's
(lldb)

I have looking for NSPersistentDocument SwiftUI example several days, but could NOT find one. Here are some similar or relation questions. Unfortunately, this problem is not solved.

EDIT: Upload this issue project to Github, https://github.com/donly/DocMacDemo.

2

There are 2 best solutions below

0
Asperi On BEST ANSWER

This is due to emptiness of new document. As in any document-based application you have to prepare some default initial data for new document

Here is possible solution. Tested with Xcode 11.4 / iOS 13.4

in Document.swift

class Document: NSPersistentDocument {

    // .. other code here

    override func makeWindowControllers() {

        // in case of new document create new empty book in context
        // that will be shown in opened document window
        let isNew = self.fileURL == nil
        if isNew {
            _ = Book(context: self.managedObjectContext!)       // << here !!
        }

        let contentView = ContentView().environment(\.managedObjectContext, self.managedObjectContext!)

        // ... other code here
0
FPP On

Well, the answer of Asperi is fine but that leaves you with a maybe not needed Book in the object model. Another way is just to save the context at the same place as suggested by Asperi:

    if let context = managedObjectContext {
        try? context.save()
    }

Then there will also be no error message from the FetchRequest.