Creating a simple note taking app for iOS in Swift

This article describes details of a simple note taking app I created in Swift for iOS.

The final product

Here is a short summary about the final app I built. With the app it is possible to:

  • Display and create notes
  • Edit notes
  • Delete notes

The app will store for each note:

  • The title of the note
  • The creation or last change date and time of the note
  • The text of the note

The new note will only be created if the note title and note text are filled. The date and time stored for the note is updated with the current date and time, when the note is edited.

The app uses UIKit, and integrates with Core Data. As a starting point the Master-detail app template is used.

Display and create notes

The app start with a screen showing the list of notes.

Displaying a note shows a screen where the note title, creation / last edited date and time, and the note text are shown.

The creation of new notes is done from the note list screen using the + button. The OK button on the create screen is only active when both the description and the text of the note are filled. The back button leaves the create screen without creating the new note.

Edit notes

From the display screen it is possible to navigate to an edit screen, which is the same as the create screen, except for that it will modify the edited note. The change can be saved with the OK button.

Delete notes

Deletion can be done by using the Edit button on the list screen. Alternatively the note can be dragged to the left, which will also delete the note.

Keywords: Apple, iOS, Swift, UIKit, Core Data, note taking app

DISCLAIMER: THE VIEWS AND OPINIONS EXPRESSED IN THIS ARTICLE ARE THOSE OF THE AUTHOR AND DO NOT REFLECT THE OFFICIAL POLICY OR POSITION OF THE EMPLOYER OF THE AUTHOR. THE ARTICLE IS NOT ENDORSED BY, DIRECTLY AFFILIATED WITH, MAINTAINED, AUTHORIZED, OR SPONSORED BY ANY CORPORATION OR ORGANIZATION. THE INFORMATION CONTAINED ON THIS ARTICLE IS INTENDED SOLELY TO PROVIDE GENERAL GUIDANCE ON MATTERS OF INTEREST FOR THE PERSONAL USE OF THE READER, WHO ACCEPTS FULL RESPONSIBILITY FOR ITS USE. ALTHOUGH THE AUTHOR HAS MADE EVERY EFFORT TO ENSURE THAT THE INFORMATION IN THIS ARTICLE WAS CORRECT AT THE TIME OF THE WRITING, THE AUTHOR DOES NOT ASSUME AND HEREBY DISCLAIM ANY LIABILITY TO ANY PARTY FOR ANY LOSS, DAMAGE, OR DISRUPTION CAUSED BY ERRORS OR OMISSIONS, WHETHER SUCH ERRORS OR OMISSIONS RESULT FROM NEGLIGENCE, ACCIDENT, OR ANY OTHER CAUSE.

Table of Content

The article is divided into the following sections:

  • Why Swift and iOS?
  • Prerequisites
  • Preparation
  • XCode Project Setup
  • Integration with Core Data
  • Creating the UI
  • Handling the actions
  • Closing words
  • References

Why Swift and iOS?

I’m not absolutely new to iOS development, although in the recent years I did not closely follow the innovation in this area. I met the iOS development first in 2011. I started to develop a mobile app prototype for the project I was working on those times. Back then Swift did not exist yet, Swift first appeared on June 2, 2014. I started learning Objective-C with the online courses of Stanford University, courses of Paul Hegarty were my favourites.

I really liked programming in Objective-C, and I wanted to learn more. However later on my interest turned to different technologies, and I didn’t continue with Objective-C. Some time ago I picked up iOS development again, and I started again with the Paul Hegarty’s Swift course on Youtube. It is a very good course to learn Swift and iOS development, with great example apps.

According to TIOBE Index for January 2019, (TIOBE index measures programming language popularity) Apple’s Swift language is on place 15.

Is it worth learning Swift nowadays? Using Swift means using Apple-based hardware, and Apple’s technology for development. No-one knows how successful the iOS platform is gong to be in the upcoming years. Even with these risks I think it definitely makes sense to start learning Swift. It will broaden your technological knowledge and understanding.

I am always excited to learn a new programming language. My opinion is that every programming language I learn offers me a new way of thinking. Writing high-quality and high-performance code has always been an art. For me getting in touch with a technology I’ve never worked with before is always time well-spent. This is especially true with a programming language with high interest.

Apple open-sourced Swift and received a lot of help from the community to grow over the last few years. Ever since its inception, it has become tremendously popular and more mature than ever. Talking about the future of this amazing programming language, the developers are not going to abandon Swift because there is nothing like a native app with good performance and a good flow. (Source: Here’s Why You Should Learn Apple’s Open Source Programming Language Swift — Analytics India Magazine)

Photo by Remy_Loz on Unsplash

Prerequisites

For this tutorial you will need the following:

  • A computer that runs Mac (If you don’t own an Apple computer, you can use MacinCloud, for example.)
  • Operating system: macOS Mojave 10.14.2 (18C54)
  • XCode (I use version 10.1 (10B61))
  • Basic Swift knowledge

Preparation

As a starting point I create a new XCode project, and start with the Master-Detail App template.

I fill the details of the new app the following way:

I don’t check “Use Core Data” because I will integrate with Core Data manually.

After creation of the new app, we can build and run it in the simulator. As you can see, this template app is a simple master-detail app, with which we can add new entries (time stamps) to a list.

By selecting an element in the list we can see a details screen.

It is also possible to remove entries from the list.

This app will be the starting point for our new iOS note taking app.

XCode Project Setup

The XCode project we build will look have the following classes and groups.

CoreDataModel group contains the model file for the Core Data integration.

Note group contains the implementation of Swift class handling the note object itself.

Storage group contains the implementation of the storage of the notes. This implementation is buit on the core data helper class, which is in the Helpers group.

Helpers group contains utility implementations for the date conversion and for the core data integration.

UI group contains the implementation of the ViewControllers, the UITableViewCell implementation assets (which is not used in this project), and the StoryBoards. (The LaunchScreen is not used in this project.)

The root folder contains the AppDelegate and the Info.plist which are created by XCode.

Integration with Core Data

For storing the notes on the mobile device I use Core Data. In Core Data we need to define a data model, which we will use in the app to store the data.

Creating a new Core Data model

In order to integrate with Core Data, we need a new Core Data model. This can be created in XCode.

Creating new Core Data model
Creating new Core Data model

Our Core Data model looks like the following. We have an entity, Note, and we have 4 attributes:

  • noteId: the internal identifier of the note. Autogenerated by the application, not shown anywhere on the UI. Type of this attribute is UUID, Universal Unique Id.
  • noteText: text of the note
  • noteTimeStamp: an integer value which contains the time stamp of the creation / last change of the note
  • noteTitle: title of the note
Core Data Model for the Really Simple Note Taking App

When creating a new XCode project we can check a checkbox which indicates that the app uses Core Data. If we check it, the app created by the template will contain the implementation to store the items in Core Data. I didn’t check this checkbox in the preparation steps, because I wanted to implement Core Data integration manually to learn it. Although I needed some code from the AppDelegate.swift, which is only generated when I use Core Data when creating the project.

This code looks like the following.

Core Data integration of AppDelegate.swift. Original file can be accessed here.

This code is needed in AppDeleage.swift. Here the name ReallySimpleNotesData in NSPersistentContainer(name: "ReallySimpleNotesData") refers to the name of the ReallySimpleNotesData.xcdatamodeld file we created.

Storing time stamp in Core Data

Storing time stamp in Core Data is an interesting topic. In Swift, the Date object has the timeIntervalSince1970 property, which is of type TimeInterval, and it contains the interval between the date value and 00:00:00 UTC on 1 January 1970. Type TimeInterval is an alias of type Double, and it means the number of seconds.

To get the seconds from this value, round it and convert it to Int64. The conversion to the other direction is also done this way. I do this by extending the Date type of Swift. This is done in ReallySimpleNoteDateHelper.swift.

Converting time stamp to seconds. Original implementation is here.

The date helper implementation also contains a method to format the date properly. With this method I can show the date on the UI in Monday, Feb 4, 2019, 11:22:33 format. The implementation of the date helper class is the following.

Date conversion helper. Original implementation here.

Note and Note Storage implementation

The Note group contains the implementation for the Note. The class ReallySimpleNote is the container of the data of a note. It can be initialized by using UUID as well as without UUID. In case the instance is created without providing a UUID from outside, the UUID is generated using the UUID which is part of the Foundation.

Implementation of ReallySimpleNote class. Original implementation is here.

The instances of ReallySimpleNote are used throughout the app to transfer note data. The notes are stored in Core Data. For handling the integration with Core Data, we have two classes:

  • ReallySimpleNoteStorage: handles the operation of creating, reading, updating and deleting a note. Holds an instance to NSManagedObjectContext, which is necessary for the integration with Core Data. The operations are forwarded to the Core Data helper class, which communicates with Core Data.
  • ReallySimpleNoteCoreDataHelper: manages the creation, reading, update and deletion of notes towards Core Data.

NSManagedContext is provided to ReallySimpleNoteStorage by the MasterViewController, in the viewDidLoad() method.

Setting managed context in the note storage, by the MasterViewController.

The note storage class, ReallySimpleNoteStorage maintains a dictionary to map note indices to noteId’s. The UI identifies the notes by their index, but in Core Data their identifier is a UUID. The mapping between these two identifiers is stored and maintained in ReallySimpleNoteStorage. Calls to ReallySimpleNoteStorage are forwared to ReallySimpleNoteCoreDataHelper. For example, reading a note by index is implemented the following way in ReallySimpleNoteStorage:

Creating a new note in note storage. Original implementation here.

Core Data helper implementation

ReallySimpleNoteCoreDataHelper class has static methods and handles the reading, modification and saving of notes to Core Data. It needs an instance of NSManagedObjectContext object, which is provided to it by using a parameter in each and every method.

For example, the creation of a new note in Core Data can be done by calling the createNoteInCoreData() method. This method is called from ReallySimpleNoteStorage.

Creating a new note with Core Data. Original implementation here.

Creating the UI

The template app we used as a starting point creates the storyboard for the app. I extended this storyboard with one more ViewController Scene. For the Master ViewController, Detail ViewController and Create/Change ViewController I have separate implementation classes.

In these ViewController classes I call helper classes to store and retrieve data from the Core Data storage. I also call the Date Helper class shown earlier.

Storyboard of the note taking app. The ViewControllers indicated are created by the template. The one on the right is the create / change ViewController created by me.

The ViewControllers are connected by Segue’s to navigate between them. Most of these Segues are created by the template app by default, but there are 3 Segue’s, which I needed to add:

  • navigation to the create screen by the + button. The template just created a new entry in the list without navigation to another screen.
  • navigation from the display screen to the change screen
  • navigation from the create / change screen back to the list of notes screen (this segue is called backToMasterView)

For these Segue’s I needed to use “Show (e.g. Push)” kind.

Navigation to create screen from the list of notes screen.

The navigation from the Create / Change screen to the main screen is implemented in the ViewController ReallySimpleNoteCreateChangeViewController by calling performSegue().

Creating a new note and changing an existing one in the ViewController. Original implementation here.

Handling the actions

UI elements are connected to class attributes with IBOutlets.

When the view was loaded

When the view was loaded, we need to set some defaults for the UI elements. This is implemented in the viewDidLoad() method. What is done here is the following:

  • set the ViewController as the delegate for the note text view
  • prefill contents of the fields when we are editing a note
  • set content of time stamp label
  • set border width, radius and color of the note text view
  • change text of back button in navigation bar
viewDidLoad() method of the create / change ViewController. Original implementation here.

Enabling / disabling the OK button

When a new note is created, the OK button should be enabled only in case there are some text entered in the title and in the text field. For this, the ReallySimpleNoteCreateChangeViewController class implements the handler for the Editing Changed and Value Changed events.

The class also implements the UITextViewDelegate protocol, so that we can react to the change of the note text. In change mode (when we edit an already existing note), the OK button is enabled by default.

For example, the handling of enabling / disabling of the OK button when the note title changes, is implemented in the following way.

Enabling / disabling OK button. Original implementation here.

The ReallySimpleNoteCreateChangeViewController is registered as a delegate for the note text view field. This way the app can react on changes to the content of the text view. For this the textViewDidChange() method was implemented.

React to the change in the note text. Original implementation here.

What’s missing?

Throughout this article and app I didn’t implement proper error handling. The code still contains TODO comment referring to appropriate error handling. This topic I will cover later in a separate article.

The Coding Hype

Articles about software development.

The Coding Hype

Articles about software development. Mainly focused on the following: Swift, Javascript, C, C++, Objective-C, Ruby, SQL, PostgreSQL, MondoDB.

László Harri Németh

Written by

Software developer. Python, SQL, ABAP, Swift, Javascript, Java, C, C++, Ruby, noSQL, Bash, Linux. http://nlharri.hu http://github.nlharri.hu hello@nlharri.hu

The Coding Hype

Articles about software development. Mainly focused on the following: Swift, Javascript, C, C++, Objective-C, Ruby, SQL, PostgreSQL, MondoDB.