I'm not sure what I'm doing wrong here, but when I save the first time into coredata, it works just fine. When I try to overwrite that, it doesn't.
func testStuff() { var token = loadLoginData() println("Token \(token)") saveLoginData("New Token") var newToken = loadLoginData() println("Token \(newToken)") } func saveLoginData(accessToken: String) { var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate) var context: NSManagedObjectContext = appDel.managedObjectContext! // save data to core data var loginData = NSEntityDescription.insertNewObjectForEntityForName("LoginData", inManagedObjectContext: context) as NSManagedObject loginData.setValue(accessToken, forKey: "accessToken") context.save(nil) println("Done saving user") } /* Output Token Optional("12345") Done saving user Token Optional("12345") */
Load Login Data Func the function that calls on saveLogin data
func loadLoginData() -> String? { var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate) var context: NSManagedObjectContext = appDel.managedObjectContext! var request = NSFetchRequest(entityName: "LoginData") request.returnsObjectsAsFaults = false var results: NSArray = context.executeFetchRequest(request, error: nil)! if (results.count > 0) { var userData: NSManagedObject = results[0] as NSManagedObject var accessToken: String = userData.valueForKey("accessToken") as String return accessToken.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) } else { println("0 results returned, potential error") return nil } }
Cause: The object you are trying to assign to a store has already been assigned and saved to a different store. Remedy: To move an object from one store to another, you must create a new instance, copy the information from the old object, save it to the appropriate store, and then delete the old instance.
You can do this: Choose "Create NSManagedObject Subclass…" from the Core Data editor menu to delete and recreate this implementation file for your updated model. You will then remove the files you already had, and the new ones will be created.
Get our help adding Core Data to your project So, with your existing project open, create a new project in Xcode (⇧⌘N) and select a Single View App, you can call it whatever you like as we'll be deleting it when we're done. You'll see the “Use Core Data” checkbox on the project options screen, make sure it is checked.
Since batchupdate is more useful in larger chunks of data, I think this is a more subtle approach.
func saveLoginData(accessToken: String, userName: String) { var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate) var context: NSManagedObjectContext = appDel.managedObjectContext! var fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "LoginData") fetchRequest.predicate = NSPredicate(format: "userName = %@", userName) if let fetchResults = appDel.managedObjectContext!.executeFetchRequest(fetchRequest, error: nil) as? [NSManagedObject] { if fetchResults.count != 0{ var managedObject = fetchResults[0] managedObject.setValue(accessToken, forKey: "accessToken") context.save(nil) } } }
I tried to translate it a bit to your situation if I'm not mistaken, but have not tested it.
fetchRequest.predicate
basically sets the filter on the attribute userName
from the entity LoginData
, with the (user)name you enter when calling the function. Assuming in this example you have only one username
with the same name. Then it does a fetchrequest
with the given filter, so you can change it's value with setValue
with the accesToken
you also enter when calling the function. The code after: if fetchResults.count != 0
, only executes when the username
exists.
Updated for Swift 4 & XCode 9.2
To answer your question...
How do you update a CoreData entry that has already been saved in Swift?
You first need to get a reference to your AppDelegate
and viewContext
. You then need to set up a NSFetchRequest
for the Entity you are looking to update, in my example that would be "Alert". You then set up your fetch to find the result you are looking for. In the example, my result found Alerts by their creation date and alert type.
To further read how to query using a predicate. Stack Overflow Example & Apple Documentation
I then context.fetch(fetchRequest)
, set the results to the value I wanted to update, and dealt with errors in a try catch. Finally I context.save()
.
let appDelegate = UIApplication.shared.delegate as! AppDelegate let context = appDelegate.persistentContainer.viewContext let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Alert") fetchRequest.predicate = NSPredicate(format: "creationDate = %@ AND alertType = %&", argumentArray: [creationDate, alertType]) do { let results = try context.fetch(fetchRequest) as? [NSManagedObject] if results?.count != 0 { // Atleast one was returned // In my case, I only updated the first item in results results[0].setValue(yourValueToBeSet, forKey: "yourCoreDataAttribute") } } catch { print("Fetch Failed: \(error)") } do { try context.save() } catch { print("Saving Core Data Failed: \(error)") }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With