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)
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.
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
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.
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
.
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.
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.
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.
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
:
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 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.
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.
The navigation from the Create / Change screen to the main screen is implemented in the ViewController ReallySimpleNoteCreateChangeViewController
by calling performSegue()
.
Handling the actions
UI elements are connected to class attributes with IBOutlet
s.
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
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.
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.
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.
Closing words
Thank you for reading this article. I hope you have learned somethinf new today. The app can be accessed on my Github profile: