How to save plist data to CoreData

Hello:


I have successfully read data from a plist and want to save that data to CoreData. From the code below I am not getting errors but it is not saving the plist data.


Please suggest what I am missing:


func preloadScq() {
     print("Call to preload Data Starts Now")
     let preloadedDataKey = "didPreloadData"
     UserDefaults.standard.removeObject(forKey: preloadedDataKey)
     let userDefaults = UserDefaults.standard
     if userDefaults.bool(forKey: preloadedDataKey) == false {
         guard let plistUrl = Bundle.main.url(forResource: "SCQ", withExtension:"plist") else {
             return
         }
        let backgroundContext = persistentContainer.newBackgroundContext()
      
        persistentContainer.viewContext.automaticallyMergesChangesFromParent = true
     
        backgroundContext.perform {
             let scqObjects = NSEntityDescription.insertNewObject(forEntityName: "SCQ", into: backgroundContext)
            if let arrayContents = NSArray(contentsOf: plistUrl) as? [String] {
           
               
                do {
                   
                let plistData = try Data(contentsOf: plistUrl)
                let scqList = try PropertyListDecoder().decode([Scq].self, from: plistData)

                for scqName in scqList {
                    let scqObject = SCQ(context: backgroundContext)
                    scqObject.answer = "answer" // the first object in the plist
                    print ("Answer is \(scqObject)") // This doesn't print anything
                }
               try backgroundContext.save()
                } catch {
                   
                    print(error)
                    print ("Your Record is Saved")
            }
        }
    }
  //

Replies

Coulkd you show all the print you get when you run ?


Notably to see if you return at line 08.

Hello Claude31:


I edited the code as below and am getting a debug list as below:


func preloadScq() {
               let backgroundContext = persistentContainer.newBackgroundContext()
                 persistentContainer.viewContext.automaticallyMergesChangesFromParent = true
                _ = NSEntityDescription.entity(forEntityName: "SCQ", in: backgroundContext)!
       
     print("Call to preload Data Starts Now")
     let preloadedDataKey = "didPreloadData"
     UserDefaults.standard.removeObject(forKey: preloadedDataKey)
     let userDefaults = UserDefaults.standard
     if userDefaults.bool(forKey: preloadedDataKey) == false {
            guard let plistUrl = Bundle.main.url(forResource: "SCQ", withExtension:"plist") else {
               return
           }
           do {
                let plistData = try Data(contentsOf: plistUrl)
                let scqList = try PropertyListDecoder().decode([Scq].self, from: plistData)
                let scqObjects = NSEntityDescription.insertNewObject(forEntityName: "SCQ", into: backgroundContext)
               print(scqList)
            for scqName in scqList {
                let scqObject = SCQ(context: backgroundContext)
  //              print(scqName)
                scqObject.answer = ("answer")
                print(scqName)
            }
                try backgroundContext.save()
                print("SAVED")
//                 userDefaults.set (true, forKey: preLoadedDataKey)
              
          
         } catch {
               print(error)
            }
        }
    }

I get a print of the plist contents:

[ScorCentMasterReview.AppDelegate.Scq(answer: "1", distractor1: "R", distractor2: "Wr", distractor3: "DK", distractor4: "not here", distractor5: "not here", grade: "2", id: "403", qid: "1", question: "If the word is spelled correctly choose R. If it is not spelled correctly choose Wr. If you don’t know choose DK. The noise was TERRIBLE.", qValue: "1000", skill: "Spell Terrible Correctly", subject: "ELA", topic: "SPELLING")


But The object that is saved is not the value for "answer" but the word "answer":

CoreData: sql: INSERT INTO ZSCQ(Z_PK, Z_ENT, Z_OPT, ZANSWER, ZDIFFICULTYLEVEL, ZDISTRACTOR1, ZDISTRACTOR2, ZDISTRACTOR3, ZDISTRACTOR4, ZDISTRACTOR5, ZGRADE, ZID, ZQVALUE, ZQID, ZQUESTION, ZSKILL, ZSUBJECT, ZTOPIC) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

CoreData: details: SQLite bind[0] = (int64)2545

CoreData: details: SQLite bind[1] = (int64)7

CoreData: details: SQLite bind[2] = (int64)1

CoreData: details: SQLite bind[3] = "answer"

Line 22, why put the string into parenthesis ?


Note: when you print for log, it's a good practice to add a label, to know exactly what you are getting:

               print("scqList", scqList)
               print("scqName", scqName)



And please show the complete log (including the initial "Call to preload Data Starts Now"

Hello Calude31:


After a week of struggle with your and 00per's suggestions, I finallg figured out the solution and as usual it was really a simple fix:


func preloadScq() {
    let backgroundContext = persistentContainer.newBackgroundContext()
        persistentContainer.viewContext.automaticallyMergesChangesFromParent = true
       _ = NSEntityDescription.entity(forEntityName: "SCQ", in: backgroundContext)!
     print("Call to preload Data Starts Now")
     let preloadedDataKey = "didPreloadData"
     UserDefaults.standard.removeObject(forKey: preloadedDataKey)
     let userDefaults = UserDefaults.standard
     if userDefaults.bool(forKey: preloadedDataKey) == false {
         guard let plistUrl = Bundle.main.url(forResource: "SCQ", withExtension:"plist") else {
             return
         }
         do {
            typealias Settings = [Scq]
            var settings: Scq?
             let plistData = try Data(contentsOf: plistUrl)
             let scqList = try PropertyListDecoder().decode([Scq].self, from: plistData)
             print(scqList)
            for items in scqList {
                print("These are the \(items)")
                let entity = NSEntityDescription.entity(forEntityName: "SCQ", in: backgroundContext)!
                let newEntity = NSManagedObject(entity: entity, insertInto: backgroundContext)
                newEntity.setValue(items.answer, forKeyPath: ("answer" as? String)!)//This line did the trick
                print ("This is the new entity \(items.answer)")
                try backgroundContext.save()
                    print("SAVED")
              }
         } catch {
             print(error)
         }
 
       
     }


Thanks.