iOS Tutorials: Saving Notes using Core Data

OVERVIEW

Core Data is a framework that allow users to store and retrieve data from it’s devices without having to retype the data every time the user uses an app. However, Core Data shouldn’t be mistaken as a database, as it is not a database.

LET’S DIVE INTO CORE DATA

Create your project and remember that this time, you’ll have to enable Core Data.

By enabling Core Data, you’ll notice an additional file on your left. First, let’s click Add Entity and create some of the attributes shown on the image such as title, details and date. Here, we are going to create a note app that allows you to input the title and details along with the date.

Let’s create our layout first by heading to Main.storyboard. These are the objects required from the Object Library. Make sure you create the required Swift file. You could do that by clicking

File > New > File > Cocoa Touch Class >

(Do it twice by creating a UITableViewController & UITableViewCell) 

The subclass should look like below in order to create the class.

(Subclass of: UITableViewCell) 

(Subclass of: UITableViewController)

Let’s get into the TableViewCell that you’ve just created and link the object together. Create an IBOutlet for each of the required object. If you don’t know how to do that, please check out my other tutorial on how to create an IBOutlet. Also, make sure to tick on Is initial View Controller on the right as we want this screen to appear first.

Lets write a function here that takes in the data from the Entity that we created earlier named Note. With this function, the data will appear on the TableView.

    func setNote(note: Note) {
        titleLabel.text = note.title
        descriptionLabel.text = note.details
        
        let date = DateFormatter()
        date.dateFormat = "MM/dd/yy/ h:mm a"
        let dateSaved = date.string(from: note.date as! Date)
        dateLabel.text = dateSaved
    }

Let’s click on the TableViewController and edit some of it’s content. Connect the layout with the class by inputting whatever name you use for the TableViewController. In my case, I use MainTableViewController.

Then create a segue by pressing Control + Drag to the other screen and click show to create a segue. Name that segue editOrAdd.

Now let’s go to the TableViewController.swift that was created few moments ago. I named mine MainTableViewController.swift. We will be  doing some coding here.

In this part of code, we will achieve:

  1. Load the notes that are saved.
  2. Enable the functionality of edit & delete on the tableview.
  3. Enable the functionality of adding a note
  4. Distribute the data to the respective area.
import UIKit
import CoreData

class MainTableViewController: UITableViewController {

    var notes = [Note]()
    
    override func viewWillAppear(_ animated: Bool) {
        loadNotes()
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    // Load the notes from Core Data
    func loadNotes() {
        let fetchRequest:NSFetchRequest<Note> = Note.fetchRequest()
        
        do {
            notes = try context.fetch(fetchRequest)
            self.tableView.reloadData()
        } catch {
            print("cannot fetch from database")
        }
    }
    
    // Functionality for delete button
    @objc func deletePressed(_ sender: UIButton){
        context.delete(notes[sender.tag])
        loadNotes()
    }
    
    // Functionality for edit button - bring you to the next screen
    @objc func editPressed(_ sender: UIButton){
        performSegue(withIdentifier: "editOrAdd", sender: notes[sender.tag])
    }
    
    // Functionality for adding notes - bring you to the next screen
    @IBAction func addPressed(_ sender: Any) {
         performSegue(withIdentifier: "editOrAdd", sender: nil)
    }
    
    // Functionality for moving to the next screen passing necessary information
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "editOrAdd"{
            if let destination = segue.destination as? ViewController {
                if let editing = sender as? Note {
                    destination.editNotes = editing
                }
            }
        } 
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return notes.count
    }
    
    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 160
    }

    // Display the following information on tableview
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell

        cell.setNote(note: notes[indexPath.row])
        cell.deleteButton.tag = indexPath.row
        cell.deleteButton.addTarget(self, action: #selector(deletePressed(_:)), for: .touchUpInside)
        
        cell.editButton.tag = indexPath.row
        cell.editButton.addTarget(self, action: #selector(editPressed(_:)), for: .touchUpInside)
        return cell
    }
}

Let’s proceed to ViewController.swift and do some necessary changes. Create an IBAction for the following button.

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var titleText: UITextField!
    @IBOutlet weak var descriptionText: UITextView!
    var editNotes: Note?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        if let note = editNotes {
            titleText.text = note.title
            descriptionText.text = note.details
        }
    }
    
    @IBAction func dismiss(_ sender: Any) {
        self.dismiss(animated: true, completion: nil)
    }
    
    @IBAction func saveNote(_ sender: Any) {
        var new: Note?
        
        if let note = editNotes {
            new = note
        } else {
        new = Note(context: context)
        }
        new?.title = titleText.text
        new?.details = descriptionText.text
        new?.date = NSDate() as Date
        
        do {
            ad.saveContext()
            self.dismiss(animated: true, completion: nil)
        } catch {
            print("cannot save")
        }
    }
}

Before we forget, go to AppDelegate.swift and add the following code below all the code:

let ad = UIApplication.shared.delegate as! AppDelegate
let context = ad.persistentContainer.viewContext

The code above allows you to access the delegate application and save the information into the database.

The code is uploaded to GitHub

  • Article By :
    Founder of DaddyCoding. Studied Computer Science, Information System and Information Technology at BYU-Hawaii. Currently spending most of my time researching and learning on helping to expose making iOS apps.

Random Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*