UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Load data to CoreData

Forums > Swift

I am trying to load some data into core data and keep getting the following error:

[error] error: No NSEntityDescriptions in any model claim the NSManagedObject subclass 'HymnTracker.HymnsPlayed' so +entity is confused. Have you loaded your NSManagedObjectModel yet ?

I have also set the module to: Current Product Module and that didnt work. Not sure what Im doing wrong.

Any help would be greatly appreciated. Thank you in advance

Here is the code im using

class ListOfHymns: ObservableObject {
    @Published var allHymns: [HymnData] = Bundle.main.decode("Hymns.json")
    @ObservedObject var userSettings = UserSettings()
    @Environment(\.managedObjectContext) var moc

    init() {
        if userSettings.loadHymns == true {
            self.loadHymnsToCoreData(for: allHymns)
//            userSettings.loadHymns = false
        }
    }

    private func loadHymnsToCoreData(for allHymns: [HymnData]) {
        for hymn in allHymns {
            let newHymnPlayed = HymnsPlayed(context: self.moc)
            newHymnPlayed.id = UUID(uuidString: hymn.id)
            newHymnPlayed.hymnName = hymn.songName
            newHymnPlayed.hymnNum = Int32(hymn.songNum)
            newHymnPlayed.playCount = 0
            do {
                try self.moc.save()
            } catch let nserror as NSError {
                fatalError("Hymn couldn't be saved. Error: \(nserror)")
            }
        }
    }
}

3      

hi,

i'm not sure what the value of moc (the ManagedObjectContext) is in this code; @Environment is something you generally use with a View and not an arbitrary class. i'm also not sure why you want ListOfHymns to have fixed data of type [HymnData] when you probably want it to contain data of type [HymnsPlayed].

if you are just trying to load data from .json into Core Data (presumably just once), and if you have some sort of MainView in your app, a quick and cheap way to load of hymns directly from your .json file into Core Data in its .onAppear() modifier, using a function in the MainView something like this:

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

    var body: some View {
        Text("Whatever you display in this view")
            .onAppear(perform: loadHymnsToCoreData)
    }

    func loadHymnsToCoreData() {
        // check to see if data has been loaded into Core Data already.
        // if not,  load data items to Core Data directly from the .json file now
        if coreDataStoreIsEmpty(self.moc) {
            var allHymns: [HymnData] = Bundle.main.decode("Hymns.json")
            for hymn in allHymns {
                let newHymnPlayed = HymnsPlayed(context: self.moc)
                newHymnPlayed.id = UUID(uuidString: hymn.id)
                newHymnPlayed.hymnName = hymn.songName
                newHymnPlayed.hymnNum = Int32(hymn.songNum)
                newHymnPlayed.playCount = 0
            }
            do {
                try self.moc.save()
            } catch let nserror as NSError {
                fatalError("Hymns couldn't be saved. Error: \(nserror)")
            }
        }
   }
}

you can build coreDataStoreIsEmpty() by doing a direct Core Data fetch for the count of HymnsPlayed entities, by adding a function on the HymnsPlayed class. something like this:

extension HymnsPlayed {
    static func count(_ context: NSManagedObjectContext) -> Int {
        let fetchRequest: NSFetchRequest<HymnsPlayed> = HymnsPlayed.fetchRequest()
        do {
            let itemCount = try context.count(for: fetchRequest)
            return itemCount
        }
        catch let error as NSError {
            print("Error counting HymnsPlayed: \(error.localizedDescription), \(error.userInfo)")
        }
        return 0
    }
}

if you need examples, i'll suggest taking a look at my ShoppingList project where i load data at startup of an app from .json files directly into Core Data if they have not been previously loaded.

finally, about your ListOfHymns class ... if all this does is track what's in Core Data, you'll have to load it from Core Data at startup (so, in the loadHymnsToCoreData function once you have a working Core Data store); but, unless there is anything special about having this class around, you might be better off using a simple @FetchRequest setup in your View.

hope that helps,

DMG

4      

@delawaremathguy thanks for the reply. The fixed data type is a struct that i use so i can loop over listOfHymns and put them into a list to display to the user. I will try to move the coredata stuff to my AppView which is a TabView.

3      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

@delawaremathguy. I don't understand this line that you suggested

if coreDataStoreIsEmpty(self.moc)

where is the coreDataStoreIsEmpty function coming from? You just said that I could build that in my class and then you put a count function in the extension.

Could you explain that to me, so I can understand it?

Thanks

3      

hi,

this is all i meant -- sorry for the confusion.

func coreDataStoreIsEmpty(context: NSManagedObjectContext) -> Bool {
  return HymnsPlayed.count(context) == 0 // i originally wrote > 0 here !!!
}

hope that helps,

DMG

3      

@delawaremathguy Thank you for getting back to me.

So am I correct in assuming that I would just create an extension of the HymnsPlayed class and add the coreDataStoreIsEmpty function to that extension?

If so then I assume I wouldn't need the count function you told me about earlier or is there some need for that?

Sorry for all the questions, Im just trying to understand how it all works.

Thanks Mark

3      

hi,

add the count function as an extension to the HymnsPlayed class as i showed. add the coreDataStoreIsEmpty function to your MainView struct.

i think that should do it,

DMG

3      

@delawaremathguy

Hi,

Thank you. I do appreciate all your help.

Mark

3      

Hi DMG @delawaremathguy,

I have my app working with coredata loading from the start. Thank you for helping me with that.

I have another question! I want to have some sort of notification/alert system that tells the user that a hymn has been added/deleted/updated in the database. How would I go about this. I have been looking at your ShoppingList Project but Im not really sure what Im looking for. So Im just spinning in circles. Could you give me some direction in how to accomplish this.

Thanks Mark

3      

hi Mark,

UPDATED ON SECOND READ ...

not sure i can help with notifications ... not something i well understand, although i'm not sure exactly what type of notifications you would need. (i use the NotificationCenter in the Shopping List project to coordinate between disparate view models, and not to communicate directly with the user of the app via using, say, the Notifications framework.) remember that this was primarily a thread about reading material from a json file and building a copy of it Core Data. we seem to have gotten that much done.

my suggestion is to start a new thread with more information about what you're trying to accomplish. , what type of notifications a user would encounter while using the app, and how such noifications would be generated. it seems far more involved than what we have seen above.

how does you app really work? how do you use the data that's now in Core Data?

i hope i can help in the future,

DMG

3      

Hi DMG,

You're right I did get accomplished what I was asking in this thread. I appreciate your help with that. I will start a new thread about the other question I have. Thanks.

Mark

3      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.