In my last articles, we created a simple application in which we inserted the details into the database and displayed them on a UITableView. In this article, we will implement the next 2 operations; i.e. Update and Delete, finally completing all the CRUD operations.
If you want to have a look at my previous two articles, then you can refer to the following links,
- Open the project in which we had implemented the Add and Display Operations in XCode.
- Our application takes Name, Age and Phone Number as inputs from the user and saves the record into our database.
- Also, it displays the database records in a table.
- So let's perform the Delete operation first.
- In the ViewController, we had added some tableView functions. Similiarly we will add one more tableView function.
- Type 'commit' in your ViewController and XCode will display a list of tableView functions. Select the tableView function containing 'commit editingStyle'. By default, it must be highlighted at the top of the list displayed by XCode.
- This function is used to add a sliding functionality to the tableview cells which gives an impressive look and feel to our application.
- It contains sliding functionality for Insert/Edit and Delete operations. Here, we are using this sliding functionality only for Delete operation.
- Paste the below code in this function.
- func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
- guard
- let appDelegate = UIApplication.shared.delegate as ? AppDelegate
- else {
- return
- }
- let managedContext = appDelegate.persistentContainer.viewContext
- let person = details[indexPath.row]
- if editingStyle == .delete {
- managedContext.delete(person as NSManagedObject)
- details.remove(at: indexPath.row)
- do {
- try managedContext.save()
- } catch
- let error as NSError {
- print("Could not save. \(error),\(error.userInfo)")
- }
- self.tableView.deleteRows(at: [indexPath], with: .fade)
- }
- }
- Now run the application and check if it works. Slide the tableview cell from right to left that you want to delete.
- Here, I am deleting the second record. On sliding, the record gets deleted.
- Stop and re-run the application and check if the record that you had deleted is now visible on the table or not. If not, then we have successfully achieved the Delete operation.
- So now, our application is successfully implemented with the Create, Read and Delete operations. So let's move to the final operation; i.e. Update.
- In my application, I am going to use a UIAlertController for the Update operation.
- When I select a particular row from my tableview, an alert box must popup which will ask the user to enter the details and will update them.
- For this, we will add another tableView function as we had added for the Delete operation.
- Type 'didSelectRowAt' and the XCode will display the tableView function containing didSelectRowAt. Select this function.
- This function allows you to select any particular row from the tableview and implement whatever you wish to do with them.
- Paste the following code inside this function.
- func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
- let person = details[indexPath.row]
- let alert = UIAlertController(title: "Update Details", message: "Update Name, Age & Phone No.", preferredStyle: .alert)
-
- let updateAction = UIAlertAction(title: "Update", style: .default, handler: {
- (action) - > Void in
-
- guard
- let newUsernameTxt = alert.textFields?.first,
- let newUsername = newUsernameTxt.text
- else {
- return
- }
- guard
- let newAgeTxt = alert.textFields ? [1],
- let newAge = Int16(newAgeTxt.text!)
- else {
- return
- }
- guard
- let newPhoneTxt = alert.textFields ? [2],
- let newPhone = Int32(newPhoneTxt.text!)
- else {
- return
- }
- self.updateData(newName: newUsername, newAge: newAge, newPhone: newPhone, person: person as!Details)
- self.tableView.reloadData()
- })
-
- alert.addTextField {
- (textField: UITextField) in textField.placeholder = "Update Name"
- }
-
- alert.addTextField {
- (textField: UITextField) in textField.placeholder = "Update Age"
- }
-
- alert.addTextField {
- (textField: UITextField) in textField.placeholder = "Update Phone No"
- }
- let cancelAction = UIAlertAction(title: "Cancel", style: .default)
- alert.addAction(updateAction)
- alert.addAction(cancelAction)
- present(alert, animated: true, completion: nil)
- }
- This code consists of the implementation of alert box with 3 text fields inside it. When you enter the details inside this alert box and press Update, the updateData function called inside this code will replace the selected row with the updated details that you have entered. For this, we need to add an updateData function too.
- Create a function updateData() inside your ViewController and paste the following code.
- func updateData(newName: String, newAge: Int16, newPhone: Int32, person: Details) {
- guard
- let appDelegate = UIApplication.shared.delegate as ? AppDelegate
- else {
- return
- }
- let context = appDelegate.persistentContainer.viewContext
- do {
- person.setValue(newName, forKey: "name")
- person.setValue(newAge, forKey: "age")
- person.setValue(newPhone, forKey: "phone")
- do {
- try context.save()
- print("Details Updated!")
- } catch
- let error as NSError {
- print("Could not save \(error), \(error.userInfo)")
- } catch {}
- } catch {
- print("Error with request: \(error)")
- }
- }
- Here is the whole ViewController.swift file containing all the codes.
- import UIKit
- import CoreData
- class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
- var details: [NSManagedObject] = []
- @IBOutlet weak
- var tableView: UITableView!@IBOutlet weak
- var txtPhoneNo: UITextField!@IBOutlet weak
- var txtAge: UITextField!@IBOutlet weak
- var txtName: UITextField!@IBOutlet weak
- var lblPhoneNo: UILabel!@IBOutlet weak
- var lblAge: UILabel!@IBOutlet weak
- var lblName: UILabel!override func viewDidLoad() {
- super.viewDidLoad()
- tableView.register(UINib(nibName: "DetailsTableViewCell", bundle: nil), forCellReuseIdentifier: "details")
- }
- override func viewWillAppear(_ animated: Bool) {
- super.viewWillAppear(animated)
-
- guard
- let appDelegate = UIApplication.shared.delegate as ? AppDelegate
- else {
- return
- }
- let managedContext = appDelegate.persistentContainer.viewContext
-
- let fetchRequest = NSFetchRequest < NSManagedObject > (entityName: "Details")
-
- do {
- details =
- try managedContext.fetch(fetchRequest)
- } catch
- let error as NSError {
- print("Could not fetch. \(error), \(error.userInfo)")
- }
- }
- @IBAction func btnAdd(_ sender: Any) {
-
- guard
- let appDelegate = UIApplication.shared.delegate as ? AppDelegate
- else {
- return
- }
- let managedContext = appDelegate.persistentContainer.viewContext
-
- let entity = NSEntityDescription.entity(forEntityName: "Details", in : managedContext) !
-
- let record = NSManagedObject(entity: entity, insertInto: managedContext)
-
- record.setValue(txtName.text, forKey: "name")
- record.setValue(Int16(txtAge.text!), forKey: "age")
- record.setValue(Int16(txtPhoneNo.text!), forKey: "phone")
- do {
- try managedContext.save()
- details.append(record)
- print("Record Added!")
-
- let alertController = UIAlertController(title: "Message", message: "Record Added!", preferredStyle: .alert)
- let OKAction = UIAlertAction(title: "OK", style: .default) {
- (action: UIAlertAction!) in
- }
- alertController.addAction(OKAction)
- self.present(alertController, animated: true, completion: nil)
- } catch
- let error as NSError {
- print("Could not save. \(error),\(error.userInfo)")
- }
- self.tableView.reloadData()
- }
- func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) - > Int {
- return details.count
- }
- func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) - > UITableViewCell {
- let person = details[indexPath.row]
- let cell = tableView.dequeueReusableCell(withIdentifier: "details",
- for: indexPath) as!DetailsTableViewCell
- cell.tblLblName?.text = (person.value(forKey: "name") ? ? "-") as ? String
- cell.tblLblAge?.text = String(describing: person.value(forKey: "age") ? ? "-")
- cell.tblLblPhoneNo?.text = String(describing: person.value(forKey: "phone") ? ? "-")
- return cell
- }
- func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
- guard
- let appDelegate = UIApplication.shared.delegate as ? AppDelegate
- else {
- return
- }
- let managedContext = appDelegate.persistentContainer.viewContext
- let person = details[indexPath.row]
- if editingStyle == .delete {
- managedContext.delete(person as NSManagedObject)
- details.remove(at: indexPath.row)
- do {
- try managedContext.save()
- } catch
- let error as NSError {
- print("Could not save. \(error),\(error.userInfo)")
- }
- self.tableView.deleteRows(at: [indexPath], with: .fade)
- }
- }
- func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
- let person = details[indexPath.row]
- let alert = UIAlertController(title: "Update Details", message: "Update Name, Age & Phone No.", preferredStyle: .alert)
-
- let updateAction = UIAlertAction(title: "Update", style: .default, handler: {
- (action) - > Void in
-
- guard
- let newUsernameTxt = alert.textFields?.first,
- let newUsername = newUsernameTxt.text
- else {
- return
- }
- guard
- let newAgeTxt = alert.textFields ? [1],
- let newAge = Int16(newAgeTxt.text!)
- else {
- return
- }
- guard
- let newPhoneTxt = alert.textFields ? [2],
- let newPhone = Int32(newPhoneTxt.text!)
- else {
- return
- }
- self.updateData(newName: newUsername, newAge: newAge, newPhone: newPhone, person: person as!Details)
- self.tableView.reloadData()
- })
-
- alert.addTextField {
- (textField: UITextField) in textField.placeholder = "Update Name"
- }
-
- alert.addTextField {
- (textField: UITextField) in textField.placeholder = "Update Age"
- }
-
- alert.addTextField {
- (textField: UITextField) in textField.placeholder = "Update Phone No"
- }
- let cancelAction = UIAlertAction(title: "Cancel", style: .default)
- alert.addAction(updateAction)
- alert.addAction(cancelAction)
- present(alert, animated: true, completion: nil)
- }
- func updateData(newName: String, newAge: Int16, newPhone: Int32, person: Details) {
- guard
- let appDelegate = UIApplication.shared.delegate as ? AppDelegate
- else {
- return
- }
- let context = appDelegate.persistentContainer.viewContext
- do {
- person.setValue(newName, forKey: "name")
- person.setValue(newAge, forKey: "age")
- person.setValue(newPhone, forKey: "phone")
- do {
- try context.save()
- print("Details Updated!")
- } catch
- let error as NSError {
- print("Could not save \(error), \(error.userInfo)")
- } catch {}
- } catch {
- print("Error with request: \(error)")
- }
- }
- }
- We are done! Let's run the application and check if it works.
- As you can see, in the above image, I have selected my first row; i.e the details of 'Anna' .We can see an alert box titled 'Update Details' with 3 text fields inside it. I am updating all 3 fields with the new data.
- After clicking on Update, the entire row is replaced by my new updated details.
- Hence, we have successfully implemented the Update operation and with this, we have implemented all the CRUD operations using Core Data Framework!
- In my next article, we will implement an alternate method for Update operations. Instead of displaying an alert box to update details, we will update our details using ID.