iOS

CRUD Parse objects in iOS

Introduction

In this section we are gonna build an iOS application that performs basic CRUD operations. CRUD is abbreviation of Create-Read-Update-Delete. When you store data on Parse it is built around ParseObject and each one contains key-value pairs of JSON-compatible data.

The values you can store in Back4App Database could be in type of String, Number, Bool, Array, Object, Date, File, Pointer, Relation and null.

You can get more information about data types by clicking here.

This tutorial uses a basic app created in Xcode 12 and iOS 14.

At any time, you can access the complete Project via our GitHub repositories.

Goal

We will develope a ToDo List App!

Here is a preview of what we are gonna achive:

Prerequisites

To complete this quickstart, you need:

Understanding our Todo App

To better understand Parse on iOS, you will see the CRUD operations implemented on a ToDo App. The application will have a simple interface, with a title text field to register a task and a list of registered tasks. You can update each task’s title.

Let’s get started!

Following the next steps, you will be able to build a Todo App that will store the tasks at Back4App Database.

Step 1 - Create Todo App Template

Go to Xcode, and find Main.storyboard layout file from the Project and then do a ViewController like this.

  • Add a Navigation Controller
  • In the Root View Controller, add a UIBarButtonItem to add a new task.
  • Add a UITableView and link with ViewController it Delegate and DataSource
  • Do a UITableViewCell with a label, a button to edit and a button to delete
  • Link the UITableView IBOutlet and the Add Button action with your ViewControler
  • Link the Cell and your itens (label, edit button and delete button) with the Cell file

Step 3 - Create Object

The create function will create a new Task with the title.

To add a TODO, we enter the title values in the pop-up that appears on the screen, set it to the ParseObject and save this object. We save this object in the database by using the function that Parse has provided us.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// function called on button create pressed
@IBAction func add(_ sender: Any) {
    openDialog(edit:false, item: nil)
}

func openDialog(edit:Bool, item: PFObject?){
    let alert = UIAlertController(title: "Item", message: "Enter a text", preferredStyle: .alert)

    alert.addTextField(configurationHandler: { (textField) -> Void in
        textField.placeholder = "Insert text here."
        if(item != nil){
            textField.text = (item!["name"] as! String)
        }
    })

    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak alert] (action) -> Void in
        let textField = (alert?.textFields![0])! as UITextField
        if(item == nil){
            self.saveNewItem(text: textField.text!)
        }else{
            item!["name"] = textField.text
            self.updateItem(item: item!)
        }
    }))

    self.present(alert, animated: true, completion: nil)
}

func saveNewItem(text: String){
    let item = PFObject(className:"Item")
    item["name"] = text
    item.saveInBackground { (success, error) in
        self.retrieveAllItens()
    }
}

Step 4 - Read Object

With the function that Parse has provided us, we can fetch all the data in a class as ParseObject list. We create a query like the one below and fetch all the data in the Todo class.

In the cellForRowAt method from UITableView we will set the edit button tag and delete button tag to equals indexPath.row. Then we know who item was pressed to edit or delete.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var listItens:[PFObject] = []
    
override func viewDidLoad() {
    super.viewDidLoad()
    self.retrieveAllItens()
}

func retrieveAllItens(){
    let query = PFQuery(className:"Item")
    query.findObjectsInBackground { (list, error) in
        self.listItens = list!
        self.tableView.reloadData()
    }
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.listItens.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ItemCell
    cell.label.text = (self.listItens[indexPath.row]["name"] as! String)
    cell.btn_edit.tag = indexPath.row
    cell.delete_btn.tag = indexPath.row
    return cell
}

Step 5 - Update Object

With the edit button in the cell of our itens displaing, we are performing our updates. In the didSelectRowAt method from UITableView will open our Alert to the user edit the item.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    self.openDialog(edit: true, item: self.listItens[indexPath.row])
}

func openDialog(edit:Bool, item: PFObject?){
    let alert = UIAlertController(title: "Item", message: "Enter a text", preferredStyle: .alert)

    alert.addTextField(configurationHandler: { (textField) -> Void in
        textField.placeholder = "Insert text here."
        if(item != nil){
            textField.text = (item!["name"] as! String)
        }
    })

    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak alert] (action) -> Void in
        let textField = (alert?.textFields![0])! as UITextField
        if(item == nil){
            self.saveNewItem(text: textField.text!)
        }else{
            item!["name"] = textField.text
            self.updateItem(item: item!)
        }
    }))

    self.present(alert, animated: true, completion: nil)
}

func updateItem(item: PFObject){
    item.saveInBackground { (success, error) in
        self.retrieveAllItens()
    }
}

Step 5 - Delete Object

We listen to the click event of the delete button in the view. When the delete button is clicked, we get the ParseObject and we call a Parse deleteInBackground function. After this we reload the itens in View.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@IBAction func deleteItem(_ sender: UIButton) {
    let refreshAlert = UIAlertController(title: "Delete", message: "Are you sure you want to delete this item?", preferredStyle: UIAlertController.Style.alert)

    refreshAlert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (action: UIAlertAction!) in
        self.listItens[sender.tag].deleteInBackground { (success, error) in
            self.retrieveAllItens()
        }
    }))

    refreshAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (action: UIAlertAction!) in
            //do nothing
    }))

    present(refreshAlert, animated: true, completion: nil)
}

It’s done!

At this point, you have learned how to do the basic CRUD operations with Parse on iOS.