Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you update a CoreData entry that has already been saved in Swift?

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     } } 
like image 400
slooker Avatar asked Oct 13 '14 17:10

slooker


People also ask

Can't reassign an object to a different store once it has been saved?

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.

How do I update my class in NSManagedObject?

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.

Can you add Core Data in existing project Swift?

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.


2 Answers

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.

like image 98
Henk-Martijn Avatar answered Sep 21 '22 17:09

Henk-Martijn


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)") } 
like image 30
Devbot10 Avatar answered Sep 19 '22 17:09

Devbot10