7

So I'm trying to setup CoreData with SwiftUI and both the CoreData model and SwiftUI views are working. All I need to do is connect them. I am able to pass a discrete number of BindableObjects but what I need is to pass an array. Here's the setup:

let peristence = PersistenceManager()
var model = [Entry]() // Entry Conforms to NSManagedObject and BindableObject
let request = Entry.createFetchRequest()
let sort = NSSortDescriptor(key: "callsign", ascending: true)
request.sortDescriptors = [sort]
do {
    model = try peristence.persistenceContainer.viewContext.fetch(request)
} catch {
    fatalError(error.localizedDescription)
}

if let windowScene = scene as? UIWindowScene {
    let window = UIWindow(windowScene: windowScene)
    window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(model))

Which produces the following error:

Instance method 'environmentObject' requires that '[Entry]' conform to 'BindableObject'

How would I make [Entry] conformant?

1 Answer 1

1

You can use a NSFetchedResultsControllerDelegate that implements BindableObject protocol and forwards the changes on a NSFetchedResultsController

class BindableFetchedResults<ResultType>: NSObject, BindableObject, NSFetchedResultsControllerDelegate where ResultType : NSFetchRequestResult {

    let controller: NSFetchedResultsController<ResultType>
    var results: [ResultType]? {
        controller.fetchedObjects
    }
    let didChange = PassthroughSubject<Void, Never>()

    init?(fetchRequest: NSFetchRequest<ResultType>, managedObjectContext context: NSManagedObjectContext) {
        self.controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
        super.init()
        self.controller.delegate = self
        do {
            try controller.performFetch()
        } catch {
            return nil
        }
    }

    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        didChange.send()
    }
}

In the code, something like this:


let persistence = PersistenceManager()
let request = Entry.createFetchRequest()
let sort = NSSortDescriptor(key: "callsign", ascending: true)
request.sortDescriptors = [sort]

guard let model =  BindableFetchedResults(fetchRequest: request, managedObjectContext: persistence.persistenceContainer.viewContext) else {
    fatalError()
}

if let windowScene = scene as? UIWindowScene {
    let window = UIWindow(windowScene: windowScene)
    window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(model))

Then you can access the entities on model.results

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.