Update Data On The Basis Of ID Using Core Data Framework

Update Data On the Basis Of Id Using Core Data Framework

 
In my previous articles, we implemented CRUD operations using Core Data Framework. In this article, we will implement update operation  using an additional attribute; i.e  an Id that we did not use till now. In my previous articles, we created an application for inserting,reading, updating and deleting the details entered by the user according to his/her wish. In this article too, we will use the same application and just modify it to perform CRUD operations on the basis of Id.
 
If you want to have a look at my previous articles regarding CRUD operations, please refer the below links:
  1. Insert Data Into A Database Using Core Data Framework
  2. Display The Records Added Into The Database On Tableview
  3. Update and Delete Operations Using Core Data Framework
So let's modify the application.
  • Open the project in XCode. First, we will make changes in our Main.storyboard. Create a new label, new textfield for Id as shown in the below image. Also, create a new button, 'Update'.
  • Connect them to your ViewController.swift file using Assistant.
  • Next, we need to add a new attribute in our .xcdatamodeld file.
Note
Make sure you delete the existing application from the simulator/ iPhone device after making the changes in your .xcdatamodeld or else your application will crash.
 
  • Next, we will add a Label in our .xib file. Open the xib file and add an extra label in the tableview cell that we had created before.
  • Connect the outlet to the TableViewCell.swift file. 
  • So far, we have successfully added a new field Id in our UI and in the xcdatamodeld file. Now, let's make the changes in our code.
  • In the btnAdd function, we had created an NSManagedObject named 'record' which sets the values for Name, Age and Phone Number. Similiarly, add one more line for the Id.
    1. record.setValue(Int16(txtId.text!), forKey: "id”)  
  • After adding this line, you will be able to add Id along with your other details into the database.
  • Add the below line in the tableview CellForRowAt function. Here, 'tblLblId' is the name that I have assigned to the new label for Id in the xib file.
    1. cell.tblLblId?.text = String(describing: person.value(forKey: "id")!)  
  • This line will display the Id that you have inserted with your record into your database.
  • As we have implemented the sliding method in our application for the Delete operation, we do not need to add any new code for Delete operation. 
  •  Now, create a new tableview function didSelectRowAt. Just type 'didSelectRowAt' and XCode will display a tableview function containing didSelectRowAt within it. Paste the code inside this function.
    1. func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {  
    2.     let cell = tableView.cellForRow(at: indexPath) as!DetailsTableViewCell  
    3.     if let id = cell.tblLblId.text {  
    4.         txtId.text = id  
    5.     }  
    6.     if let name = cell.tblLblName.text {  
    7.         txtName.text = name  
    8.     }  
    9.     if let age = cell.tblLblAge.text {  
    10.         txtAge.text = age  
    11.     }  
    12.     if let phone = cell.tblLblPhoneNo.text {  
    13.         txtPhoneNo.text = phone  
    14.     }  
    15. }  
  • As the name suggests, the above code will display the details of the record that you have selected from the tableview in the text fields.
  • Run the application and check if it works. You must be able to view the data in the textfields of the row that you have selected from the tableview.
  •  Create a new function or update the existing function updateData and paste the following code.
    1. func updateData() {  
    2.     guard  
    3.     let appDelegate = UIApplication.shared.delegate as ? AppDelegate  
    4.     else {  
    5.         return  
    6.     }  
    7.     let managedContext = appDelegate.persistentContainer.viewContext  
    8.     let entity = NSEntityDescription.entity(forEntityName: "Details"in : managedContext)  
    9.     let request = NSFetchRequest < NSFetchRequestResult > ()  
    10.     request.entity = entity  
    11.     let predicate = NSPredicate(format: "(id = %@)", txtId.text!)  
    12.     request.predicate = predicate  
    13.     do {  
    14.         let results =  
    15.             try managedContext.fetch(request)  
    16.         let objectUpdate = results[0] as!NSManagedObject  
    17.         objectUpdate.setValue(txtName.text!, forKey: "name")  
    18.         objectUpdate.setValue(Int32(txtPhoneNo.text!), forKey: "phone")  
    19.         objectUpdate.setValue(Int16(txtAge.text!), forKey: "age")  
    20.         do {  
    21.             try managedContext.save()  
    22.             print("Record Updated!")  
    23.         } catch  
    24.         let error as NSError {}  
    25.     } catch  
    26.     let error as NSError {}  
    27. }  
  • In the above code, we used NSPredicate which fetches/filters data according to the specified format. As we have assigned Id to it, it will fetch the data on the basis of Id. 
  • Call this function inside the btnUpdate function.
    1. @IBAction func btnUpdate(_ sender: Any) {  
    2.     updateData()  
    3.     self.tableView.reloadData()  
    4. }  
  •  Below is the entire ViewController.swift file for your reference.
    1. import UIKit  
    2. import CoreData  
    3. class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {  
    4.     var details: [NSManagedObject] = []  
    5.     @IBOutlet weak  
    6.     var tableView: UITableView!@IBOutlet weak  
    7.     var txtId: UITextField!@IBOutlet weak  
    8.     var txtPhoneNo: UITextField!@IBOutlet weak  
    9.     var txtAge: UITextField!@IBOutlet weak  
    10.     var txtName: UITextField!@IBOutlet weak  
    11.     var lblPhoneNo: UILabel!@IBOutlet weak  
    12.     var lblAge: UILabel!@IBOutlet weak  
    13.     var lblName: UILabel!@IBOutlet weak  
    14.     var btnUpdate: UIButton!override func viewDidLoad() {  
    15.         super.viewDidLoad()  
    16.         tableView.register(UINib(nibName: "DetailsTableViewCell", bundle: nil), forCellReuseIdentifier: "details")  
    17.     }  
    18.     override func viewWillAppear(_ animated: Bool) {  
    19.         super.viewWillAppear(animated)  
    20.         //1  
    21.         guard  
    22.         let appDelegate = UIApplication.shared.delegate as ? AppDelegate  
    23.         else {  
    24.             return  
    25.         }  
    26.         let managedContext = appDelegate.persistentContainer.viewContext  
    27.         //2  
    28.         let fetchRequest = NSFetchRequest < NSManagedObject > (entityName: "Details")  
    29.         //3  
    30.         do {  
    31.             details =  
    32.                 try managedContext.fetch(fetchRequest)  
    33.         } catch  
    34.         let error as NSError {  
    35.             print("Could not fetch. \(error), \(error.userInfo)")  
    36.         }  
    37.     }  
    38.     @IBAction func btnAdd(_ sender: Any) {  
    39.         //1  
    40.         guard  
    41.         let appDelegate = UIApplication.shared.delegate as ? AppDelegate  
    42.         else {  
    43.             return  
    44.         }  
    45.         let managedContext = appDelegate.persistentContainer.viewContext  
    46.         //2  
    47.         let entity = NSEntityDescription.entity(forEntityName: "Details"in : managedContext) !  
    48.             //3  
    49.             let record = NSManagedObject(entity: entity, insertInto: managedContext)  
    50.         //4  
    51.         record.setValue(Int16(txtId.text!), forKey: "id")  
    52.         record.setValue(txtName.text, forKey: "name")  
    53.         record.setValue(Int16(txtAge.text!), forKey: "age")  
    54.         record.setValue(Int16(txtPhoneNo.text!), forKey: "phone")  
    55.         do {  
    56.             try managedContext.save()  
    57.             details.append(record)  
    58.             print("Record Added!")  
    59.             //To display an alert box  
    60.             let alertController = UIAlertController(title: "Message", message: "Record Added!", preferredStyle: .alert)  
    61.             let OKAction = UIAlertAction(title: "OK", style: .default) {  
    62.                 (action: UIAlertAction!) in  
    63.             }  
    64.             alertController.addAction(OKAction)  
    65.             self.present(alertController, animated: true, completion: nil)  
    66.         } catch  
    67.         let error as NSError {  
    68.             print("Could not save. \(error),\(error.userInfo)")  
    69.         }  
    70.         self.tableView.reloadData()  
    71.     }  
    72.     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) - > Int {  
    73.         return details.count  
    74.     }  
    75.     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) - > UITableViewCell {  
    76.         let person = details[indexPath.row]  
    77.         let cell = tableView.dequeueReusableCell(withIdentifier: "details",  
    78.             for: indexPath) as!DetailsTableViewCell  
    79.         cell.tblLblId?.text = String(describing: person.value(forKey: "id") !)  
    80.         cell.tblLblName?.text = (person.value(forKey: "name") ? ? "-") as ? String  
    81.         cell.tblLblAge?.text = String(describing: person.value(forKey: "age") ? ? "-")  
    82.         cell.tblLblPhoneNo?.text = String(describing: person.value(forKey: "phone") ? ? "-")  
    83.         return cell  
    84.     }  
    85.     func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {  
    86.         guard  
    87.         let appDelegate = UIApplication.shared.delegate as ? AppDelegate  
    88.         else {  
    89.             return  
    90.         }  
    91.         let managedContext = appDelegate.persistentContainer.viewContext  
    92.         let person = details[indexPath.row]  
    93.         if editingStyle == .delete {  
    94.             managedContext.delete(person as NSManagedObject)  
    95.             details.remove(at: indexPath.row)  
    96.             do {  
    97.                 try managedContext.save()  
    98.             } catch  
    99.             let error as NSError {  
    100.                 print("Could not save. \(error),\(error.userInfo)")  
    101.             }  
    102.             self.tableView.deleteRows(at: [indexPath], with: .fade)  
    103.         }  
    104.     }  
    105.     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {  
    106.         let cell = tableView.cellForRow(at: indexPath) as!DetailsTableViewCell  
    107.         if let id = cell.tblLblId.text {  
    108.             txtId.text = id  
    109.         }  
    110.         if let name = cell.tblLblName.text {  
    111.             txtName.text = name  
    112.         }  
    113.         if let age = cell.tblLblAge.text {  
    114.             txtAge.text = age  
    115.         }  
    116.         if let phone = cell.tblLblPhoneNo.text {  
    117.             txtPhoneNo.text = phone  
    118.         }  
    119.     }  
    120.     @IBAction func btnUpdate(_ sender: Any) {  
    121.         updateData()  
    122.         self.tableView.reloadData()  
    123.     }  
    124.     func updateData() {  
    125.         guard  
    126.         let appDelegate = UIApplication.shared.delegate as ? AppDelegate  
    127.         else {  
    128.             return  
    129.         }  
    130.         let managedContext = appDelegate.persistentContainer.viewContext  
    131.         let entity = NSEntityDescription.entity(forEntityName: "Details"in : managedContext)  
    132.         let request = NSFetchRequest < NSFetchRequestResult > ()  
    133.         request.entity = entity  
    134.         let predicate = NSPredicate(format: "(id = %@)", txtId.text!)  
    135.         request.predicate = predicate  
    136.         do {  
    137.             let results =  
    138.                 try managedContext.fetch(request)  
    139.             let objectUpdate = results[0] as!NSManagedObject  
    140.             objectUpdate.setValue(txtName.text!, forKey: "name")  
    141.             objectUpdate.setValue(Int32(txtPhoneNo.text!), forKey: "phone")  
    142.             objectUpdate.setValue(Int16(txtAge.text!), forKey: "age")  
    143.             do {  
    144.                 try managedContext.save()  
    145.                 print("Record Updated!")  
    146.             } catch  
    147.             let error as NSError {}  
    148.         } catch  
    149.         let error as NSError {}  
    150.     }  
    151. }  
  • We have successfully modified the code! Let's run the application and check if it works.
  • Add some records into your database. Select any of the row from your tableview and change its details. Click on Update button. Check if the record gets updated.
  • Note
    Avoid updating the Id field. You may update the other fields but if you change the Id, the application will crash. 
     
  • In the above image example, I have changed the Age field of my 2nd record from 17 to 20. After clicking on the Update button, the record gets updated as well as I get a message of 'Record Updated!' on my output window.
  • So we have successfully implemented the Update operation along with other operations on the basis of Id.