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

后端 未结 14 2600
有刺的猬
有刺的猬 2020-11-30 00:55

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         


        
相关标签:
14条回答
  • 2020-11-30 01:41

    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

    0 讨论(0)
  • 2020-11-30 01:41

    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)")
        }
    }
    
    0 讨论(0)
  • 2020-11-30 01:43

    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
            }
    
    0 讨论(0)
  • 2020-11-30 01:46

    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.

    0 讨论(0)
  • 2020-11-30 01:46

    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)
    }
    
    0 讨论(0)
  • 2020-11-30 01:55

    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.

    0 讨论(0)
提交回复
热议问题