Let's make an app where you can create messages that persist in Core Data.
- Set up core data model (
.xcdatamodeld
) from scratch. - Configure boilerplate code for data store to interact with Core Data / SQLite database.
- Learn basics of fetching/saving with Core Data.
Open up the project. We've set up a blank tableview controller and started DataStore
. Your job is to setup Core Data, display your persistent Message
objects, and add an interface where users can create and save new messages.
Before we work on any views, we need to prepare our models for Core Data. This part has much more 'explaining' than 'coding', but it's important! So soak up the knowledge.
- First, let's create our data model (
.xcdatamodeld
). Create a new file, select the "Core Data" section on the left, then choose "Data Model". Usually we give this the same name as our project, so let's name it "slapChat". - Go to your new .xcdatamodeld file and create an entity ("Add Entity" button near the bottom) and name it
Message
. Give it two attributes:content
(String) andcreatedAt
(Date, though this is stored in Core Data as anNSDate
). A singular name is used for each entity (e.g.,Message
rather thanMessages
), even if we know we're going to have multiples of the entity later on. This is because we're really dealing with multiple entities, each entity being its own instance of aNSManagedObject
subclass. Wouldn't it be weird to say we're going to set thecontent
of aMessages
? - Make sure each attribute's Optional property is unchecked out.
Our .xcdatamodeld
is set up, so now let's prepare DataStore
so that it can fetch/save with Core Data.
- Check out
DataStore.swift
. We've set a few things up for you: a singleton calledsharedInstance
, a private initializer, apersistentContainer
, and the functionsaveContext()
. The last two of these actually come prebuilt in yourAppDelegate
when you create a new project and specify the use of Core Data. It's common practice to move them to a Data Store, however, for better organization of your code. - Your task is to setup
fetchData()
.- This is DataStore, so add an
Array
property on this class to hold your fetched objects. Name itmessages
. - Implement
fetchData()
to create anNSFetchRequest
, have your contextfetch
it, set the results to yourmessages
array, and sortmessages
by their creation dates.
- This is DataStore, so add an
Hint: The context is retrieved by calling
persistentContainer.viewContext
.
That's it! Your model and data store are now ready to fetch and save Message
s.
-
We can't display messages if we haven't created any! Let's do this in
TableViewController
.- Create a
store
property to hold your Data Store'ssharedInstance
. - In
viewDidLoad()
create a fewMessage
s. UseNSEntityDescription
's class functioninsertNewObject(forEntityName:into:)
. - Don't forget to set your test messages'
content
andcreatedAt
properties!
- Create a
-
So now is when you'd want to
saveContext()
so that these messages would persist in our database. BUT, since this is inviewDidLoad()
, that means that we'd be creating and saving new messages every time we run our app. Let's add some logic to prevent that.- Make a new method called
generateTestData()
. Dump all your message creation in there, and make your dataStoresaveContext()
andfetchData()
at the end. The reason wefetchData()
here is to ensure themessages
property on ourstore
singleton is completely up-to-date. - In
viewDidLoad()
,fetchData()
and then pass your dataStore's messages to your local messages array. - Logic time -
if
your messages array is still empty, callgenerateTestData()
and pass them again.
- Make a new method called
-
Run it a couple times and either
print()
or breakpoint/po
your local messages array to make sure you're not saving a ton of duplicates. Assuming all went well, we can finally get some stuff on the screen!
Less talk; more walk.
- Set your cell style to
Basic
and its reuse identifier tomessageCell
. - Set up your data source. Make each cell display the
content
of its corresponding message.
Run it to make sure it works. Comment out your generateTestData()
check to prove that the messages are actually persisting. Revel in your persistent data's glory.
Let's keep rollin' with our theme of "just do it":
- Add a plus button to the navigation bar and link it to a new view controller. Name the class
AddMessageViewController
. - Add a save button and a text field. When you tap save, make it:
- create a new message with the contents of the text field,
- save the context,
- dismiss the view controller.
- Cool! Except the new message didn't show up in our tableView... In your tableView controller, override
viewWillAppear()
so that it:- fetches data,
- updates your local messages,
- reloads the tableView.
- Give it another shot. When the
AddMessageViewController
is dismissed, your tableView will display the new message.
- Add a button that resorts the messages in the array to descending by the
createdAt
property. - Take your
generateTestData()
method out ofTableViewController
and put it where it belongs (DataStore
).
View SlapChat on Learn.co and start learning to code for free.