CoreData not updating when saved (Swift)

I am trying to get the data I update in an entity within CoreData to save; however, I change the values and yet it doesn't save. Here's the basics of how I am doing this:

var container: NSPersistentContainer!
var theSettings: Settings!
var collectionSize: Int

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = container.viewContext
theSettings = Settings.init(context: context)

collectionSize = Int(theSettings.defaultSize) // This works sets the value correctly

// Later when the user changes a setting I do this

theSettings.defaultSize = 6

do {

     try appDelegate.persistentContainer.viewContext.save()

} catch let error as NSError {

     print("Error: \(error), \(error.userInfo)")

}

I've checked and the persistentContainer is correctly setup in the appDelegate. However, the value goes back to the default once I leave the view. It never saves. I've checked all over and I can't see anything that I'm doing wrong. I've done a lot of iOS programming, but this is the first time I'm using CoreData.

Thanks for any help you can offer.

Answered by michaeljmac in 694543022

I did end up figuring out what was wrong with the BOOL attributes. You have to make sure you set the "Use Scalar Types" in the "Attributes" tab of the Attribute that is a BOOL. When you do that you can set it with a variable in code that is a BOOL.

Just wanted to completely close this out.

Why do you:

  • manage data in context (container.viewContext)
  • save appDelegate.persistentContainer.viewContext and not context

Try to change

     try appDelegate.persistentContainer.viewContext.save()

with

     try context.save()

That's how it shows to do it. So, I'm not sure what I would change those to.

That's how it shows to do it.

Who shows ?

Did you try the change I proposed in the do { } ?

I was simply following the instructions in a book I got on Core Data. However, I'm now beginning to see what the problem is. In doing a FetchRequest, it now shows 69 items in the "defaultSize" attribute of the "Settings" entity.

It seems that every time the user makes a change, it simply adds a new record with that "defaultSize", instead of replacing the existing "defaultSize" with the new user selected size.

Maybe I'm just not understanding the process here. I'm simply trying to use Core Data to keep all the user preferences (in Objective-C I used NSUserDefaults. But with the switch to Swift, I decided to switch to Core Data (for various reasons other than just the language change)).

So, I guess my question is this: I just want to hold a single value in the "defaultSize" attribute of the "Settings" entity in Core Data. It starts with a default value of 5 and I want to change that value to a new user selected value whenever the user chooses to do so.

Is the information I provided here enough to be able to show that? I've read in multiple places that I can simply use the "theSettings.defaultSize = 6" code and then save the context, but that doesn't just update the value, it is adding new values to an array within the default size.

(as a weird side note - when I delete the App off the simulator and start from scratch - the very first time I run it from Xcode it shows three values in the "defaultSize" attribute. I find that odd since I have yet to select any and it should be the default of 5 listed in the xcdatamodeld file in Xcode)

I've attached the setup for the managed objects. The code that I used to access and update the attributes is above. And I've described the actions I'm trying to get to. If there's anything I need to supply, please let me know.

As I've gone through Apple's documentation. I changed some of my code to follow their examples. This is what I use to try to update the attribute based on the user's input:

do {

     let fetchedSize = try appDelegate.persistentContainer.viewContext.fetch(sizeFetch)

     for data in fetchedSize as! [NSManagedObject] {

          data.setValue(Float(collectionSize), forKey: "defaultSize")

     }

} catch {

     fatalError("Failed to fetch size: \(error)")

}

do {

     try appDelegate.persistentContainer.viewContext.save()

} catch {

     fatalError("Failed to save: \(error)")

}

If I do another fetch after the "setValue" piece, the correct values show up. However, once I leave that view and come back, my update never got saved. It goes back to the original defaultValue. Just to note, I also changed the value of the "defaultSize" attribute to be a Float.

Ok, so, I think I've figured out the problem that was causing my issues.

I found some code that I missed from testing. The issues stem from trying out different methods of creating and using core data.

I found a line of "init" code that kept creating new instances of the core data model. Each time, it would reset all the data to the default and when I tried to pull the "changed" attributes, it was pulling it from the new instance, which of course would return the defaults. Now, that I've clean out all the core data code and went back to add in just the fetch methods to retrieve and update the attributes, they now update as expected, except for the Bool attributes. They don't seem to save.

So, I'm still working on why that is happening. If anyone has any thoughts, it would be greatly appreciated.

Thanks for those that have responded. It helped me to start thinking in the right direction.

Accepted Answer

I did end up figuring out what was wrong with the BOOL attributes. You have to make sure you set the "Use Scalar Types" in the "Attributes" tab of the Attribute that is a BOOL. When you do that you can set it with a variable in code that is a BOOL.

Just wanted to completely close this out.

CoreData not updating when saved (Swift)
 
 
Q