0
votes

I have AppName.xcdatamodeld file, with Category in Entities. In Category I successfully add records from SwiftUI and successfully fetch them in View like so:

import SwiftUI
import CoreData

struct CategoriesList: View {
    @Environment(\.managedObjectContext) var moc
    
    var fetchRequest: FetchRequest<CountdownCategory>
    var countdownCategories: FetchedResults<CountdownCategory> {
        fetchRequest.wrappedValue
    }
    
    var body: some View {
        ForEach(countdownCategories, id: \.self) { countdownCategory in
            Text(countdownCategory.title ?? "Category")
        }
    }
    
    init() {
        fetchRequest = FetchRequest<CountdownCategory>(entity: CountdownCategory.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \CountdownCategory.dateAdded, ascending: false)])
    }
}

Now I need to execute same query in different place of a program - not in SwiftUI view, but in a method in a class:

import Foundation
import CoreData

class Categories {
    func getCategories() {
        let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        let categoriesFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "CountdownCategory")
         
        do {
            let categoriesFetch = try moc.fetch(categoriesFetch) as! [CountdownCategory]
        } catch {
            fatalError("Failed to fetch categories: \(error)")
        }
        
        // etc.
    }
}

I looked up sample code in official Core Data documentation, however when I try to execute this I get an error:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSPersistentStoreCoordinator for searching for entity name 'CountdownCategory''

Would appreciate any help with fixing that error. My goal is to get data from Core Data from CountdownCategory in this method. (Swift 5.2)

UPD #1: when I use let categoriesFetch = CountdownCategory.fetchRequest() I get an error:

Ambiguous use of 'fetchRequest()'

UPD #2: when I use let categoriesFetch: NSFetchRequest<CountdownCategory> = CountdownCategory.fetchRequest() I do not get a crash. But how do I get data?

1

1 Answers

1
votes
let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)

You're making a brand new managed object context here, with no backing persistent store or model. That's not the right way to do it. You need to use the same context you passed in to your SwiftUI environment object, wherever that came from.

You've said that the app delegate has an NSPersistentContainer so I'm guessing you've used the SwiftUI / Core Data app template. In that case you need to replace the line of code above (let moc = ...) with something like this:

let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

If you are using the template, you can look in SceneDelegate.swift and see where the context is injected into the SwiftUI environment using similar code.