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 t
There's a new feature called Batch Updates.
I think this article will help you:
http://www.bignerdranch.com/blog/new-in-core-data-and-ios-8-batch-updating/
Basicly what you do is use the NSBatchUpdateRequest
instead of NSFetchRequest
, filter the results with NSPredicate
, change the value in the results, and save the data.
Another tutorial in swift:
http://code.tutsplus.com/tutorials/ios-8-core-data-and-batch-updates--cms-22164
In swift 4 or swift 5, you can used like bellow
func update(accessToken:String,username:String){
//1
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
//2
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "LoginData")
// 3
let predicate = NSPredicate(format: "%K == %@", "username", username)
fetchRequest.predicate = predicate
//3
do {
let rs = try managedContext.fetch(fetchRequest)
for result in rs as [NSManagedObject] {
// update
do {
var managedObject = rs[0]
managedObject.setValue(accessToken, forKey: "accessToken")
try managedContext.save()
print("update successfull")
} catch let error as NSError {
print("Could not Update. \(error), \(error.userInfo)")
}
//end update
}
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
It worked for me you should try this:
let managedContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Students", in: managedContext)
let request = NSFetchRequest<NSFetchRequestResult>()
request.entity = entity
let predicate = NSPredicate(format: "(name = %@)", txtName.text!)
request.predicate = predicate
do {
var results =
try managedContext.fetch(request)
let objectUpdate = results[0] as! NSManagedObject
objectUpdate.setValue(txtName.text!, forKey: "name")
objectUpdate.setValue(txtPhone.text!, forKey: "phone")
objectUpdate.setValue(txt_Address.text!, forKey: "address")
do {
try managedContext.save()
txtName.text = ""
txtPhone.text = ""
txt_Address.text = ""
labelStatus.text = "Updated"
}catch let error as NSError {
labelStatus.text = error.localizedFailureReason
}
}
catch let error as NSError {
labelStatus.text = error.localizedFailureReason
}
You're creating multiple new LoginData
objects, but your loadLoginData
method is always returning the same object, the first one from the fetch request results.
You want to keep updating the same object, so you need to change your saveLoginDetails
method.
Instead of creating a new object (which is what insertNewObjectForEntityName
) does, use the loadLoginDetails
method to get your existing one, and change the property on there.
It worked for me, you should try this:
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return}
let managedContext = appDelegate.persistentContainer.viewContext
// if object nil is checked if new entity will be created or created one will be updated
if object == nil {
// create new entity:
let entityObj = NSEntityDescription.entity(forEntityName: "EntityName", in: managedContext)!
let entity = NSManagedObject(entity: entityObj, insertInto: managedContext)
entity("new value", forKeyPath: "entityValue")
do {
try managedContext.save()
entities.append(entity)
self.navigationController?.popViewController(animated: true)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
else {
// the created entity will be updated selected object is entity -> came from previous view controller:
self.entity?.setValue("updated value", forKey: "entityValue")
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
self.navigationController?.popViewController(animated: true)
}
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.