[IOS] TodoList with Core Data (Xcode 9.2 and Swift 4)

 

Many people get confused when working with Core Data. Core data is not a database. It is an object graph manager  and it handles the duties the data model in MVC. It is a persistence framework and it is performant.

Alternatives include Realm and Firebase which are very good if you plan to build cross platform apps.

 

//MARK: Creating the Project

In this tutorial we are going to start off with a single view app and we are going to name it TodoList with CoreData. We are going to choose Use Core Data. On the next screen, I am going to select Create Git Repository on MAC because I want to upload the project to Github.

Create Xcode Project with Core Data

 

//MARK: Creating the Model

The first thing that we will do is work on our object graph. So let’s create one by selecting File>New> File> Core Data. You may have to scroll down to see Core Data.

Create Core Data Model

 

You can name the model what ever you like or you can leave it as the default model. We are going to select our data from the navigator and click on add entity. An entity is like a class in swift.

Add Entity to Project with Core Data

The entity can be customized by giving it a name and attributes. Think of the attributes as being similar to the properties in a class.

Core Data add Attributes

We are going to give this entity two attributes. The first one is going to be called name. The type is going to be a string and we must deselect the box making it optional(it is selected in the picture). The second attribute will be called completed and we will make it a boolean and we can set the default value to NO. Just like before we need to make sure that the optional checkbox is not selected.

//MARK: Creating the Table View

Let’s go to our main storyboard and replace the view controller with a table view controller. In the attributes inspector set it to the initial view controller.

Go to ViewController.swift file and subclass UITableViewController. Rename the class to ToDoViewController. Your code should look like this:

 

Let’s return to the Main.storyboard and select our table view controller. Go to the identity inspector and in the class section set it to TodoViewController.

Set class in identity inspector

Select the table view cell from the document outline and in the attribute inspector give the cell a name of Item and hit enter.

identifier of cell in table view

Let’s embed the Table View controller in a navigation controller by selecting Editor>Embed In>Navigation Controller. This allows to add a bar button item which we can change to a plus button which can be used to add items to our table.

Drag a bar button item to the right of our navigation item and also set a title for the navigation item. When you are done it should look like the one below.Add title and bar button item

//MARK: Adding Code to Our View Controller

Let’s navigate to our TodoViewController.swift and add import Core Data. Add the following lines of code below our class declaration.

The first line stores an empty array of Items objects in a variable named items. The second line references our persistent container. If you take a look in the AppDelegate.swift you will notice that you have a persistence container. This constant that we created goes into the app delegate and grabs the persistence container.

//MARK: Table View Datasource Methods:

The datasource methods are the methods responsible for populating our table with information. We are going to need:

  1. numberOfRowsInSection
  2. cellForRowAt indexPath

 

The first method returns an integer. So we will set it to return the size of our items variable by using the .count method.

The second method returns a cell so we must first create a cell using tableView.dequeReusableCell(withIdentifier: String, for: IndexPath).  This returns a reusable table-view cell object for the specified reuse identifier and adds it to the table. The string is the name that we gave to our cell in the main storyboard and iIndexPath = indexPath. The index path is used to specify the location of the cell. We must next create a variable named item (the name is up to you) to store one item from the items array. We then set the text label of the cell to the name of the item. If the item is completed the cell will have an accessoryType of  checkmark and if it is not completed, there will be no checkmark. This is done using the ternary operator. Finally we return the cell. Your code should look like the one below.

//MARK: Setting up the Add Button

Create an IBAction by control and dragging from the plus button to the view controller. Let’s create it at the bottom of our class. We can name the button addItems.  When this button is pressed it will create an alert that allows us to add items to our tableview.

  • Create a UItextField and store it in a variable named textfield.
  • Create an alertController with a title: “Add New Item“; the message can be an empty string; the preferredStyle can be set to .alert and store it in a variable named alert.
  • Create a UIAlertAction with a title: “Save” and a style of .default and in the closure, create a newItem; set the name to what is added in the textField. Add the item to our items array; and then save the items(we will create a method to save the items later).
  • Add the action to the alert.
  • Add the text field to the alert.
  • Present the alert

Your code should look like this:

 

//MARK: Create a function named saveItems()

To save with core data we just need to use try context.save() but this throws an error. So we need to place it in a do-catch block.  Then we must reload the data in the tableView. Your code should look like the one below:

 

//MARK: TableView Delegate Methods

The delegate methods are responsible for what happens when you click on a cell. We are going to need:

  1. didSelectRow
  2. canEditRowAt indexPath
  3. commit editingStyle

 

didSelectRow

We when we click on a cell we want to be able to add a checkmark and we don’t want the cell to be highlighted in grey. Whenever we click a cell it sets the completed attribute to true and we click it again. It sets it to false. Your didSelectRow method should look like this:

 

canEditRowAt indexPath

This method is pretty straightforward. We just need to set this method to return true.

 

commit editingStyle

If the editing style is delete we are first going to create a constant that represents a single item. We then remove that item from the particular index path; delete the item from the context and then save the context. Finally we call .deleteRows on the table view. This updates the UI so that we don’t have to call .reloadData. Your code should look like this.

  

 

//MARK: Create a Method to load items

The last thing that we need to do is create a method that allows us to load the data into the app when it starts. We can do this by using an NSFetchReequest. An instance of NSFetchRequest collects the criteria needed to select and optionally to sort a group of managed objects held in a persistent store. Then we try to fetch this request from the context and set it equal to our items array. This throws an error so it must be placed in a do-catch block. Your code should look like this:

 

Close Menu