4 Replies
      Latest reply on Mar 11, 2020 7:51 AM by macmark.de
      narcisfromgirona Level 1 Level 1 (0 points)

        I update one field in Core Data. This code works well:

         

        func updateData(){
                guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
                let managedContext = appDelegate.persistentContainer.viewContext
                let fetchRequest:NSFetchRequest = NSFetchRequest.init(entityName: "User")
                fetchRequest.predicate = NSPredicate(format: "username = %@", "John")
               
                do {
                    let test = try managedContext.fetch(fetchRequest)
                    let objectUpdate = test[0] as! NSManagedObject
                    objectUpdate.setValue("John2", forKey: "username")
                    objectUpdate.setValue("John2@example.com", forKey: "email")
                    objectUpdate.setValue("newPassword", forKey: "password")
                    do {
                        try managedContext.save()
                    }
                    catch {
                        print(error)
                    }
                } catch {
                    print(error)
                }
            }

         

        I would like to add a way to check if what I try to update exists. In that specific case, I want to check first if I have in the database the username John

        • Re: Check before the update in Core Data
          DelawareMathGuy Level 3 Level 3 (190 points)

          hi,

           

          i think the code you wrote looks workable -- although you did not mention any error or say exactly what it is you want to do that the current code doesn't appear do for you.  unless, of course, you're simply asking what is the value of objectUpdate in line 9 and you want to check that new values have been assigned to its attributes -- and you might just print(objectUpdate.username) before line 10 and again after line 10.

           

          nevertheless, i'd suggest you might want to go over to Youtube.com and search for "Stanford CS193P 2017"  watch the episodes Lecture 10 (Core Data) and Lecture 11 (Core Data Demo).  i think you'll find those very helpful at this stage (even though this was in 2017, everything you'll see pretty much works as is today).

           

          hope that helps,

          DMG

            • Re: Check before the update in Core Data
              narcisfromgirona Level 1 Level 1 (0 points)

              Thank you for the reference to the videos. I will love to study that.

               

              func updateData() is a simple code to create data in Core Data that I found in a tutorial. There is no error there, it is ok. What I miss in that code is a way to check if the value I want to update exists in Core Data.

               

              For instance, the example is looking for John. If it finds it, it will change it to John2. But, if in the database there is no John, that will not work, of course. So, I need to add something like the conditional that I put at the beginning. My question is how can I say in that example "if (you find the username John in Core Data) ..."

                • Re: Check before the update in Core Data
                  DelawareMathGuy Level 3 Level 3 (190 points)

                  hi,

                   

                  if all you want is a "did it succeed" indication, you could use something like this, returning a boolean that indicates whether everything worked:

                   

                  func updateData() -> Bool {
                    var success = false
                    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return success }
                    let managedContext = appDelegate.persistentContainer.viewContext
                    let fetchRequest = NSFetchRequest.init(entityName: "User")
                    fetchRequest.predicate = NSPredicate(format: "username = %@", "John")
                  
                    do {
                      let test = try managedContext.fetch(fetchRequest)
                      if test.count == 1 {
                        let objectUpdate = test[0] as! NSManagedObject
                        objectUpdate.setValue("John2", forKey: "username")
                        objectUpdate.setValue("John2@example.com", forKey: "email")
                        objectUpdate.setValue("newPassword", forKey: "password")
                        appDelegate.saveContext() // look in AppDelegate.swift for this function
                        success = true
                      }
                    } catch {
                      print(error)
                    }
                    return success
                  }

                   

                  check the return value of updateData() to issue your success message:

                   

                  if updateData() {
                    print ("I have found the name and I have changed")
                  } else {
                    print ("I could not find the name you are looking for")
                  }

                   

                  there are many variations on how to use what's above -- it's not the best code, it may not generalize well to whatever you specifically are doing, and the appDelegate may throw/catch an error in saveContext() that would not be recognized in this code.

                   

                  but then, consider: your code would be cleaner and less prone to error if you used what XCode generates for you for whatever class of managed object you defined in the .xcdatamodeld file.  if, for example, the NSManagedObject you're working with was defined as an entity named User -- with attributes named username, email, and password (all String types) -- this code should work (i think -- i did not test, but it mirrors code i have in a current project)

                   

                  func updateData() -> Bool {
                    var success = false
                    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return success }
                    let managedContext = appDelegate.persistentContainer.viewContext
                    let fetchRequest: NSFetchRequest<User> = User.fetchRequest() // this provided by XCode code generation
                    fetchRequest.predicate = NSPredicate(format: "username = %@", "John")
                  
                    do {
                      let test = try managedContext.fetch(fetchRequest)
                      if test.count == 1 {
                        let userToUpdate = test[0]
                        userToUpdate.username = "John2"
                        userToUpdate.email = "John2@example.com"
                        userToUpdate.password = "newPassword"
                        appDelegate.saveContext() // look in AppDelegate.swift for this function
                        success = true
                      }
                    } catch {
                      print(error)
                    }
                    return success
                  }

                   

                  hope that helps,

                  DMG

                   

                  ** EDIT A DAY LATER: line 5 above was updated to provide specificity for the type of fetchRequest as NSFetchRequest<User>.

              • Re: Check before the update in Core Data
                macmark.de Level 1 Level 1 (0 points)

                Do it this way

                • set the NSFetchRequestResultType of the NSFetchRequest to NSCountResultType
                • excecute the NSFetchRequest by using the method countForFetchRequest on the NSManagedObjectContext
                • check if the returned count is greater than zero