【问题标题】:How do you update a CoreData entry that has already been saved in Swift?如何更新已经保存在 Swift 中的 CoreData 条目?
【发布时间】:2014-12-08 07:47:52
【问题描述】:

我不确定我在这里做错了什么,但是当我第一次保存到 coredata 时,它工作得很好。当我尝试覆盖它时,它不会。

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")
*/

加载登录数据功能 调用 saveLogin 数据的函数

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
    }
}

【问题讨论】:

    标签: ios core-data swift


    【解决方案1】:

    有一个称为批量更新的新功能。

    我认为这篇文章会对你有所帮助:

    http://www.bignerdranch.com/blog/new-in-core-data-and-ios-8-batch-updating/

    基本上你所做的就是使用NSBatchUpdateRequest而不是NSFetchRequest,使用NSPredicate过滤结果,更改结果中的值,然后保存数据。

    另一个快速教程:

    http://code.tutsplus.com/tutorials/ios-8-core-data-and-batch-updates--cms-22164

    【讨论】:

      【解决方案2】:

      您正在创建多个新的 LoginData 对象,但您的 loadLoginData 方法始终返回相同的对象,即获取请求结果中的第一个对象。

      您想不断更新同一个对象,因此您需要更改您的saveLoginDetails 方法。

      不要创建一个新对象(这是insertNewObjectForEntityName 所做的),而是使用loadLoginDetails 方法获取您现有的对象,然后更改那里的属性。

      【讨论】:

      • 不,我应该每次都使用同一个。我肯定做错了。
      【解决方案3】:
      var context: NSManagedObjectContext = appDel.managedObjectContext!
      var en = NSEntityDescription.entityForName("ENTITIES_NAME", inManagedObjectContext: context)
      let batchUpdateRequest = NSBatchUpdateRequest(entity: en!)
      batchUpdateRequest.resultType = NSBatchUpdateRequestResultType.UpdatedObjectIDsResultType
      batchUpdateRequest.propertiesToUpdate = ["OBJECT_KEY": "NEWVALUE"]
      var batchUpdateRequestError: NSError?
      context.executeRequest(batchUpdateRequest, error: &batchUpdateRequestError)
      if let error = batchUpdateRequestError {
          println("error")
      }
      

      祝你好运

      【讨论】:

        【解决方案4】:

        由于批量更新在更大的数据块中更有用,我认为这是一种更微妙的方法。

        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)
                }
            }
        }
        

        如果我没记错的话,我试着把它翻译成你的情况,但没有测试过。

        fetchRequest.predicate 基本上设置了来自实体LoginData 的属性userName 的过滤器,使用调用函数时输入的(用户)名称。假设在此示例中您只有一个具有相同名称的 username。然后它使用给定的过滤器执行fetchrequest,因此您可以使用setValue 更改它的值,并在调用函数时输入您也输入的accesToken。后面的代码: if fetchResults.count != 0 ,仅在 username 存在时执行。

        【讨论】:

        • 你必须把 appDel.在 managedObjectContext!.executeFetchRequest 之前,所以正确的代码行应该是这样的: if let fetchResults = appDel.managedObjectContext!.executeFetchRequest(fetchRequest, error: nil) as? [NSManagedObject] {
        • 您也可以只使用您已经存储在内存中的上下文,无需再次访问它。只需context.executeFetchRequest(...)
        • 我认为在 try 块中添加 executeFetchRequest 会更好。此处未处理错误
        • 你能解释一下 NSPredicate(format: "userName = %@", userName) 它的请求结构是什么意思吗?
        【解决方案5】:

        Swift >= 2 该方法现在返回一个非可选的并在错误情况下抛出一个错误,必须使用 try-catch 处理:

        let context = self.fetchedResultsController.managedObjectContext
        let entity = self.fetchedResultsController.fetchRequest.entity!
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity.name!)
        fetchRequest.predicate = NSPredicate(format: "notificationId = 13")
        
        do {
            let list = try context.executeFetchRequest(fetchRequest) as? [NSManagedObject]
            // Check notificationId available then not save
            if list!.count == 0 {
                let newManagedObject = NSEntityDescription.insertNewObjectForEntityForName(entity.name!, inManagedObjectContext: context)
                newManagedObject.setValue("This is first message13", forKey: "message")
                newManagedObject.setValue(1, forKey: "appId")
                newManagedObject.setValue(13, forKey: "notificationId")
                newManagedObject.setValue("First one", forKey: "tital")
            }
            // success ...
        } catch let error as NSError {
            // failure
            print("Fetch failed: \(error.localizedDescription)")
        }
        

        【讨论】:

        • 谢谢!我认为您在设置值后可能需要newManagedObject.save(),对吗?
        【解决方案6】:

        为 Swift 4 和 XCode 9.2 更新

        回答你的问题……

        如何更新已经保存在 Swift 中的 CoreData 条目?

        您首先需要获得对您的AppDelegateviewContext 的引用。然后,您需要为要更新的实体设置NSFetchRequest,在我的示例中为“警报”。然后,您设置您的 fetch 以找到您正在寻找的结果。在示例中,我的结果按创建日期和警报类型找到了警报。

        进一步阅读如何使用谓词进行查询。 Stack Overflow Example & Apple Documentation

        然后我 context.fetch(fetchRequest),将结果设置为我想要更新的值,并在 try catch 中处理错误。 最后我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)")
        }
        

        【讨论】:

        • 核心数据数据库更新后会发生什么?我是否有办法倾听这些变化?谢谢
        【解决方案7】:

        它对我有用,你应该试试这个:

        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)
        }
        

        【讨论】:

          【解决方案8】:

          它对我有用,你应该试试这个:

          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
                  }
          

          【讨论】:

          • 尽量使用正确的拼写、标点和语法。
          【解决方案9】:

          步骤:1 - 创建新项目并选择“使用核心数据” 通过:“https://medium.com/@ankurvekariya/core-data-crud-with-swift-4-2-for-beginners-40efe4e7d1cc

          步骤:2 - 内部 ViewController (userList)

          import UIKit
          import CoreData
          
          class ViewController: UIViewController, UITableViewDelegate , UITableViewDataSource {
          
          var arrUser = Array<Any>()
          @IBOutlet var tableView: UITableView!
          
          override func viewDidLoad() {
              super.viewDidLoad()
          
              self.title = "User List"
              self.tableView.separatorStyle = .none
              self.retrieveData(Delete: false, indexpath: 0)
          
              let logoutBarButtonItem = UIBarButtonItem(image: UIImage(named: "addImage"), style: .done, target: self, action: #selector(addNewUser))
              self.navigationItem.rightBarButtonItem  = logoutBarButtonItem
          }
          
          override func viewDidAppear(_ animated: Bool)
          {
              super.viewDidDisappear(animated)
              self.retrieveData(Delete: false, indexpath: 0)
          }
          
          @objc func addNewUser(){
              let userVC = self.storyboard?.instantiateViewController(withIdentifier: "AddUser_VC") as! AddUser_VC
              self.navigationController?.pushViewController(userVC, animated: true)
          }
          
          //MARK: - TableView DataSource Delegate
          func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
              return self.arrUser.count
          }
          
          func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
          
              let cell = tableView.dequeueReusableCell(withIdentifier: "UserCell") as! UserCell
              cell.selectionStyle = .none
              let dictData = self.arrUser[indexPath.row] as? NSManagedObject
              cell.lblName.text = dictData?.value(forKey: "name") as? String ?? ""
              cell.lblPost.text = dictData?.value(forKey: "post") as? String ?? ""
              cell.lblEmail.text = dictData?.value(forKey: "email") as? String ?? ""
              cell.lblPhone.text = String(dictData?.value(forKey: "phone") as? Int ?? 0)
              cell.imageData?.image =  UIImage(data: dictData?.value(forKey: "image") as? Data ?? Data())
          
              return cell
          }
          
          func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
              return 140
          }
          
          func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
          
              let dictData = self.arrUser[indexPath.row] as? NSManagedObject
              let AddUserVC = self.storyboard?.instantiateViewController(withIdentifier: "AddUser_VC") as! AddUser_VC
              AddUserVC.isEdit  = true
              AddUserVC.dictObj = dictData
              self.navigationController?.pushViewController(AddUserVC, animated: true)
          
          }
          
          func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
              return true
          }
          
          func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
              if (editingStyle == .delete) {
                  //self.deleteData(indexpath: indexPath.row)
                  self.retrieveData(Delete: true, indexpath: indexPath.row)
              }
          }
          
          //MARK: - retrieveData
          func retrieveData(Delete:Bool , indexpath:Int) {
          
              guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
              let managedContext = appDelegate.persistentContainer.viewContext
              let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "UserTable")
          
              if (Delete == true)
              {
                  do
                  {
                      let test = try managedContext.fetch(fetchRequest)
          
                      let objectToDelete = test[indexpath] as! NSManagedObject
                      managedContext.delete(objectToDelete)
          
                      do{
                          try managedContext.save()
                          self.retrieveData(Delete: false, indexpath: 0)
                      }
                      catch
                      {
                          print(error)
                      }
                  }
                  catch
                  {
                      print(error)
                  }
              }
          
              do {
                  self.arrUser = try managedContext.fetch(fetchRequest)
                  self.tableView.reloadData()
                  print(self.arrUser)
              } catch {
                   print("Failed")
              }
          }
          }
          

          第 3 步 - 在 UserCell 内部

          import UIKit
          
          class UserCell: UITableViewCell {
          
          
          @IBOutlet var lblName: UILabel!
          @IBOutlet var lblEmail: UILabel!
          @IBOutlet var lblPost: UILabel!
          @IBOutlet var lblPhone: UILabel!
          @IBOutlet var imageData: UIImageView!
          
          override func awakeFromNib() {
              super.awakeFromNib()
              self.imageData.layer.cornerRadius = self.imageData.frame.height / 2
              self.imageData.layer.borderWidth = 1.0
              self.imageData.layer.borderColor = UIColor.lightGray.cgColor
              self.imageData.layer.masksToBounds = true
          }
          
          override func setSelected(_ selected: Bool, animated: Bool) {
              super.setSelected(selected, animated: animated)
          
              // Configure the view for the selected state
          }
          
          }
          

          步骤:4 - 在 AddUserVC 中

          import UIKit
          import CoreData
          
          class AddUser_VC: UIViewController ,UIImagePickerControllerDelegate ,UINavigationControllerDelegate {
          
          var dictObj: NSManagedObject!
          var isEdit:Bool = false
          
          @IBOutlet var imageData: UIImageView!
          @IBOutlet var txtName: UITextField!
          @IBOutlet var txtEmail: UITextField!
          @IBOutlet var txtPost: UITextField!
          @IBOutlet var txtPhone: UITextField!
          
          @IBOutlet var btnAddUser: UIButton!
          
          
          override func viewDidLoad() {
              super.viewDidLoad()
          
              self.imageData.layer.cornerRadius = self.imageData.frame.height / 2
              self.imageData.layer.borderWidth = 1.0
              self.imageData.layer.borderColor = UIColor.lightGray.cgColor
              self.imageData.layer.masksToBounds = true
          
              let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
              self.imageData.isUserInteractionEnabled = true
              self.imageData.addGestureRecognizer(tapGestureRecognizer)
          
              if (self.isEdit == true)
              {
                  self.txtName.text = dictObj.value(forKey: "name") as? String ?? ""
                  self.txtEmail.text = dictObj.value(forKey: "email") as? String ?? ""
                  self.txtPost.text = dictObj.value(forKey: "post") as? String ?? ""
                  self.txtPhone.text = String(dictObj.value(forKey: "phone") as? Int ?? 0)
                  self.imageData?.image = UIImage(data: dictObj?.value(forKey: "image") as? Data ?? Data())
                  self.btnAddUser.setTitle("UPDATE", for: .normal)
              }
          }
          
          
          //MARK: - btnAddUserAction Method -
          @IBAction func btnAddUserAction(_ sender: Any) {
          
              let arrData = [self.txtName,self.txtEmail,self.txtPost,self.txtPhone]
              for txt in arrData
              {
                  if (txt?.text == "")
                  {
                      let alert = UIAlertController(title: "Alert", message: "Please Enter All Fields", preferredStyle: UIAlertController.Style.alert)
                      alert.addAction(UIAlertAction(title: "Click", style: UIAlertAction.Style.default, handler: nil))
                      self.present(alert, animated: true, completion: nil)
                      return
                  }
              }
          
              self.createData()
          }
          
          //MARK: - Image Tap Method -
          @objc func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
          {
              let alert = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet)
              alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: { _ in
                  self.openCamera()
              }))
          
              alert.addAction(UIAlertAction(title: "Gallery", style: .default, handler: { _ in
                  self.openGallery()
              }))
          
              alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
          
              self.present(alert, animated: true, completion: nil)
          }
          
          func openCamera()
          {
              if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) {
                  let imagePicker = UIImagePickerController()
                  imagePicker.delegate = self
                  imagePicker.sourceType = UIImagePickerController.SourceType.camera
                  imagePicker.allowsEditing = false
                  self.present(imagePicker, animated: true, completion: nil)
              }
              else
              {
                  let alert  = UIAlertController(title: "Warning", message: "You don't have camera", preferredStyle: .alert)
                  alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
                  self.present(alert, animated: true, completion: nil)
              }
          }
          
          func openGallery()
          {
              if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary){
                  let imagePicker = UIImagePickerController()
                  imagePicker.delegate = self
                  imagePicker.allowsEditing = true
                  imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
                  self.present(imagePicker, animated: true, completion: nil)
              }
              else
              {
                  let alert  = UIAlertController(title: "Warning", message: "You don't have permission to access gallery.", preferredStyle: .alert)
                  alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
                  self.present(alert, animated: true, completion: nil)
              }
          }
          
          
          func imagePickerController(_ picker: UIImagePickerController,
                                     didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
              guard (info[.originalImage] as? UIImage) != nil else {
                  fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
              }
               self.imageData.image = info[.originalImage] as? UIImage
              picker.dismiss(animated: true, completion: nil)
          }
          
          //MARK: - createData
          func createData(){
          
              guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
              let managedContext = appDelegate.persistentContainer.viewContext
              let userEntity = NSEntityDescription.entity(forEntityName: "UserTable", in: managedContext)!
          
              var user = NSManagedObject()
              if(isEdit == true)
              {
                   user = self.dictObj
              }
              else
              {
                  user = NSManagedObject(entity: userEntity, insertInto: managedContext)
              }
          
              let image = self.imageData.image!.jpegData(compressionQuality: 0.5)as NSData?
              user.setValue(self.txtName.text, forKeyPath: "name")
              user.setValue(self.txtEmail.text, forKey: "email")
              user.setValue(self.txtPost.text, forKey: "post")
              user.setValue(Int(self.txtPhone.text!), forKey: "phone")
              user.setValue(image, forKey: "image")
          
              do {
                  try managedContext.save()
                  self.navigationController?.popViewController(animated: true)
          
              } catch let error as NSError {
                  print("Could not save. \(error), \(error.userInfo)")
              }
          }
          
          } 
          

          替代方法:

          //MARK: - CoreData Methods -
          func createData(){
              guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
              let managedContext = appDelegate.persistentContainer.viewContext
              let userEntity = NSEntityDescription.entity(forEntityName: "Movie", in: managedContext)!
              for obj in self.MoviewList.arrMovieData{
                  let user = NSManagedObject(entity: userEntity, insertInto: managedContext)
                  user.setValue(obj.id, forKey: "id")
                  user.setValue(obj.title, forKey: "title")
                  user.setValue(obj.overview, forKey: "overview")
                  let url = API.IMAGE_BASE_URL + obj.poster_path
                  user.setValue(url, forKey: "poster_path")
             }
              do {
                  try managedContext.save()
              } catch let error as NSError {
                  print("Could not save. \(error), \(error.userInfo)")
              }
          }
          
          
          func retrieveData() {
          
              guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
              let managedContext = appDelegate.persistentContainer.viewContext
              let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Movie")
              do {
                  let result = try managedContext.fetch(fetchRequest)
                  var arr = [[String:AnyObject]]()
                  for data in result as! [NSManagedObject] {
                      var obj = [String:AnyObject]()
                      obj["id"] = data.value(forKey: "id") as AnyObject
                      obj["title"] = data.value(forKey: "title") as AnyObject
                      obj["overview"] = data.value(forKey: "overview") as AnyObject
                      obj["poster_path"] = data.value(forKey: "poster_path") as AnyObject
                      arr.append(obj)
                  }
                  self.MoviewList = MovieDataList(data: arr)
                  self.tableView.reloadData()
              } catch {
          
                  print("Failed")
              }
          }
          
          func deleteAllRecords() {
              let delegate = UIApplication.shared.delegate as! AppDelegate
              let context = delegate.persistentContainer.viewContext
          
              let deleteFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Movie")
              let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetch)
          
              do {
                  try context.execute(deleteRequest)
                  try context.save()
                  self.createData()
              } catch {
          
              }
          }
          

          【讨论】:

            【解决方案10】:

            这对我有用。首先,我使用 fetchRequest.predicate 通过给定属性“taskName”设置过滤器。然后我获取已保存的数据并为“状态”设置值以更新该对象。

            func updateTaskStatus(status: Bool){
            
                guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
                let managedContext = appDelegate.persistentContainer.viewContext
                let fetchRequest: NSFetchRequest<Task> = Task.fetchRequest()
                let predicate = NSPredicate(format: "(taskName = %@)", (task?.taskName)!)
                fetchRequest.predicate = predicate
                do {
                    let result = try managedContext.fetch(fetchRequest)
                    task = result[0] as NSManagedObject as? Task
                    task?.setValue(status, forKey: "status")
                    do {
                        try managedContext.save()
                    }catch  let error as NSError {
                        print("\(error)")
                    }
                }catch let error as NSError {
                    print("\(error)")
                }
            }
            

            【讨论】:

              【解决方案11】:

              在swift 4或swift 5中,你可以像下面这样使用

              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)")
                  }
              }
              

              【讨论】:

              • 首先,为了以后参考,这段代码的部分来源是here。其次,这段代码看起来不是很干净。例如,当您只访问第一个结果时,为什么要迭代结果?为什么嵌套了不需要的 do 语句?
              【解决方案12】:

              斯威夫特 5

              您可以创建一个既适用于包含又适用于更新的方法。 假设您在 CoreData 上创建了一个名为 Usersentity

               var context: NSManagedObjectContext {
                  let appDelegate = UIApplication.shared.delegate as! AppDelegate
                  return appDelegate.persistentContainer.viewContext
               }
              
               let user: Users!
              
               let fetchUser: NSFetchRequest<Users> = Users.fetchRequest()
               fetchUser.predicate = NSPredicate(format: "id = %@", id as String)
              
               let results = try? context.fetch(fetchUser)
              
               if results?.count == 0 {
                  // here you are inserting
                  user = Users(context: context)
               } else {
                  // here you are updating
                  user = results?.first
               }
              
               user.id = id
               user.name = name
               ...
              
              
              try context.save()
              

              【讨论】:

              • 谢谢!你为我节省了一些时间!在为 Web 服务调用返回数据后,我在 Swift UI 函数中使用了我所做的调整。 record_id 是服务器上包含的唯一字段,因此您可以将其添加到您的“关键”字段
              • 实体名称应该是单数:Users -> User.
              【解决方案13】:

              //对于 Swift UI 里面的 view 里面的 body :)
              @Environment(.managedObjectContext) var managedObjectContext

              var isNewRecord = false
              let aNewContact: Contact!
              let fetchContact: NSFetchRequest<Contact> = Contact.fetchRequest() as! NSFetchRequest<Contact>
              fetchContact.predicate = NSPredicate(format: "record_id == %@", contactRemoteModel.contacts[i].record_id as CVarArg)
              let results = try? managedObjectContext.fetch(fetchContact)
              
              if results?.count == 0 {
                  // here you are inserting
                  aNewContact = Contact(context: managedObjectContext)
                  aNewContact.id = UUID()
                  isNewRecord = true
                  print("Insert")
              } else {
                  // here you are updating
                  aNewContact = results?.first
                  print("UpDate")
              }
              

              【讨论】:

                【解决方案14】:
                #Update Data in #CoreData #iOS #swift 
                
                Simply follow below steps to update data in CoreData which you already saved 
                
                #Step1 :- refer to persistent container & create object of viewContext
                let appDelegate = UIApplication.shared.delegate as! AppDelegate
                let viewContext = appDelegate.persistentContainer.viewContext
                
                #Step2 :- create FetchRequest
                let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "User") // here User is entity name 
                
                //Step3 :- add predicate to fetch request by passing attribute and value 
                fetchRequest.predicate = NSPredicate(formate: "userName = %@","XYZ")
                
                //Step4 :- fetch record using viewContext by passing fetchRequest and set new value in it 
                do {
                  let results = try viewContext.fetch(fetchRequest) as? [NSManagedObject] 
                  if result?.count !=0 {
                      result?[0].setValue("ABC",forKey: "userName")
                  } 
                } catch {
                  print("failed to fetch record from CoreData")
                }
                
                //Step5 :- finally call save method of viewcontext so new value get reflect in CoreData
                  do {
                    viewContext.save()
                } catch {}
                
                Note :- in predicate the value "XYZ" can be value of attribute and format will contain name of attribute such like username , age password ....etc , in result?[0].setValue you can set new value for particular attribute by passing value and keynote , you can skip step5 and can execute save method inside step4 after Line where we setting new value
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-10-05
                  • 1970-01-01
                  • 2021-10-24
                  • 1970-01-01
                  相关资源
                  最近更新 更多