iOS – Core Data

In this tutorial you will learn how to use core data to save items in a simple to-do list app. To follow along it is recommended to follow the previous tutorial on adding items dynamically in a UITableView or you can download the previous iOS project. To start learning iOS Application Development, you will need a Mac computer and Xcode, Apple’s Integrated Development Environment (IDE). This tutorial makes use of the Swift Programming Language. Hence before diving into iOS application development, it is recommended to have at least a basic knowledge of the Swift Programming Language.

Core Data

In our previous tutorial we added dynamic items in a UITableView. We checked the Use Core Data at the beginning of the creation of the iOS project. Core Data is used to save data. In our previous tutorial, you must have noticed that each time we launched the app, we lost the items we added. In this tutorial, we will save the added items in Core Data so that they are always available in the app. Click on the SampleToDoList.xcdatamodeld file.

In the bottom-left of the editor, click on Add Entity. You will notice an Entity is created under the ENTITIES heading in the top-left of the editor.

Double-click the Entity and name it Task.

Under the Attributes section in the editor, click on the plus button. Rename the added attribute to item and select String as its type.

Create a new Cocoa Touch Class, select NSObject as its subclass and name it DatabaseHelper.

Copy and paste the following codes in your DatabaseHelper class.

import UIKit
import CoreData

class DatabaseHelper: NSObject {
    static let shared = DatabaseHelper()
    
    func insert(item: String) {
        let context = AppDelegate().persistentContainer.viewContext
        let entity = NSEntityDescription.insertNewObject(forEntityName: "Task", into: context)
        
        entity.setValue(item, forKey: "item")
        
        do {
            try context.save()
        } catch let error {
            print("Could not save item. Error: \(error.localizedDescription)")
        }
    }
    
    func getAll() -> [NSManagedObject]? {
        let context = AppDelegate().persistentContainer.viewContext
        let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Task")
        
        do {
            return try context.fetch(request) as? [NSManagedObject]
        } catch let error {
            print("Could not fetch items. Error: \(error.localizedDescription)")
        }
        
        return nil
    }

}

The DatabaseHelper will handle the codes for insertion of a new item and retrieval of saved items in Core Data. Select your ToDoListController and replace the following codes in it.

import UIKit

class ToDoListController: UITableViewController {
    var items = [String]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 3
        loadItems()
    }
    
    // MARK: - IBAction
    
    @IBAction func addDidPressed(_ sender: UIBarButtonItem) {
        showTextField()
    }
    
    private func showTextField() {
        let alertController = UIAlertController(title: "New Item", message: "", preferredStyle: .alert)
        
        alertController.addTextField { (textField) in
            textField.placeholder = "Enter a new item"
        }
        
        let okAction = UIAlertAction(title: "OK", style: .default) { (_) in
            if let textField = alertController.textFields?.first, let newItem = textField.text, !newItem.isEmpty, newItem.count > 0 {
                self.items.append(newItem)
                // 1
                DatabaseHelper.shared.insert(item: newItem)
                self.tableView.reloadData()
            }
            
            alertController.dismiss(animated: true, completion: nil)
        }
        
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in
            alertController.dismiss(animated: true, completion: nil)
        }
        
        alertController.addAction(okAction)
        alertController.addAction(cancelAction)
        
        present(alertController, animated: true, completion: nil)
    }
    
    // 2
    private func loadItems() {
        if let itemObjs = DatabaseHelper.shared.getAll() {
            for itemObj in itemObjs {
                let item = itemObj.value(forKey: "item") as? String ?? ""
                items.append(item)
            }
        }
        
        tableView.reloadData()
    }
    
    // MARK: - Table view data source
    
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath)
        
        let item = items[indexPath.row]
        cell.textLabel?.text = item
        
        return cell
    }
    
    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            items.remove(at: indexPath.row)
            tableView.reloadData()
        }
    }
}

In the ToDoListController class, we

  1. save the new item to Core Data by calling our DatabaseHelper‘s method insert(item:).
  2. define a function to load the items found in Core Data in our global variable items.
  3. call the function loadItems().

Run your project and add new items in the app. Now you will always have the added items saved in your app.

Well done! 😀 You now have a basic knowledge of Core Data. Awesome! 😀