A Core Data Tutorial Part 1

UPDATE 2 Aug 2011: Some of you have requested a revised version of this tutorial that covers Xcode 4, I have completed that post and it is now located here. You should also note that I will not be adding any tutorials to this site anymore as I have moved my blog to my main development website theMikeSwan.com.

This is the first in a series of tutorials that combines other tutorials I have seen and in the end will go a little past the others I have seen. My intention is to take this app from beginning to end, including the finishing touches like update checking, serial number, and icons. I am writing this to help me figure out a few things about Core Data and hopefully help others as well.

This tutorial assumes you have the Apple Developer Tools installed and are familiar with basic operation of Xcode and Interface Builder. It also assumes that you have a very basic knowledge of Core Data. If you are completely new to Core Data check out either Build a Core Data App or read chapters 11 & 30 of Aaron Hillegass’s book Cocoa Programming for Mac OS X 3rd Edition. Really if you are new to Cocoa you should have a copy of Aaron’s book no matter what, it is the one book I always go to when I’m not sure about something. We will also be doing a little with bindings, if you need a starter check out either Cocoa Bindings Intro or Chapter 11 of Aaron’s book.

This is the first tutorial in the series so we should first specify our goal. First off the purpose of the app will be to track daily expenses. Every feature we think about adding should be assessed based on that one sentence, this will hopefully help keep down the feature creep. Since the purpose of the app is to track expenses we will just call it Expenses. Now we should determine the major features of the app. It will of course need to store expenses, perhaps when, what, & how much. To make life easier it would be a good idea to be able to assign each expense a category so the user can figure out things like how much they spend on food versus movies. It would also be good to show how much was spent in a month on any one category, as well as overall (this is a feature I will need some help with). Of course we will also show yearly totals both by category and overall. We are also going to want to let the user know when we release new version of the app without having to e-mail them (they don’t want the e-mail and will ignore it). Since we are putting all this effort into writing this Expenses perhaps we want to get paid for it, in which case we will want some way to require a serial number for real use of the app. Finally in order to improve the user experience we should get crash reports so we can figure out how to reduce (if not eliminate) them. Of course along the way we will come up with a few smaller features (such as copy and paste of expenses) that we will add in, but this should be the bulk of it. We will use Core Data to build Expenses because it is extremely well suited to this kind of work and will reduce the amount of code we have to write dramatically.

Today we are going to start by just building the basic app without writing any code at all!

To start with open Xcode and start a new Document based Core Data application.

New Project

Name it Expenses (or whatever you want to call it).

Next set up the model as below.

Attributes:

Expense

Category

Name

Type

Name

Type

desc

string

name

string

date

date

amount

float

Relationships:

Expense

Category

Name

Destination

Name

Destination

category

Category

expenses

Expense (to-Many)

In the end the model should look like this:

Picture 4

Make sure you save.

Next let’s build the user interface.

Open MyDocument.xib

Remove the Label.

Add a tab view.

Size it to take up most of the window.

TabView

In the inspector select the size tab and set the springs and struts so that the tab view resizes with the window.

Size Inspector

Label one of the tabs “Expenses” and the other “Categories.”

Tab Labels

Make sure the Expenses tab is active, then drag over a Core Data Entity from the IB Library. It will bring up the “New Core Data Entity Interface” assistant:

Select Expenses -> MyDocument -> Expense as below, then click next.

Entity 1

In the next pane select “Detail/Master View” and select “Detail Field” & “Add/Remove.” If you want you can also select “Search Field” to get basic searching for free.

Entity 2

In the last pane select all of the attributes and the one relationship:

Entity 3

You should have something that looks similar to the image below. It needs a little work, first off lets get rid of that extra box (Layout -> Unembed Objects).

Default layout

Next lets make a few other tweaks. Date should really be the first column; Description, the second; followed by Amount, and Category. Amount will need it’s number formatter adjusted to display currency in whatever way you want. You will likely want to adjust the date formatter in the date column (unless you want the really long default format). Then resize the the table and it’s columns to something resembling the image below. Once that is done collect all the detail fields and put them in a box at the bottom. you will also need to adjust the formatters for the date and amount fields to match the ones in the table view (unless you want them to be different of course). In the end it should look something like this:

Expense Layout

Before we do the other tab we should make life easier if we have to change any bindings later. You should have two array controllers in you xib file now, one named “Expense Array Controller” and one named “Category Array Controller.” When you drop the Category entity into the other tab IB will add in another “Category Array Controller” making it very hard to tell which is which. To eliminate this problem rename “Expense Array Controller” to “ExpenseView Array Controller” and “Category Array Controller” to “CategoryPopUp Array Controller” this just makes everything way more clear for the future.

Now select the Categories tab and drop a Core Data Entity on it. follow the same procedure as before (only select the Category entity of course). Re-arrange the interface to look like below. Go ahead and rename the new “Category Array Controller” to “CategoryView Array Controller.”

Category Layout

If you are wondering what that huge empty space is for, it’s for the table view that you need to add now. It should have three columns; Date, Description, and Amount. Below the table view add two labels; “Total:” and a placeholder with a number formatter set to your favorite currency settings (I tend to use “$10,000,000.00” as my place holder since it should always be big enough for any numbers I will ever be entering).

FinalCat

Now to fill that nice new table view with some data. First add a new array controller and name it “ExpenseByCat Array Controller.” Now your xib file should look something like this:

xib file

See how easy it is to figure out which array controller does what.

In the bindings section of the inspector for “ExpenseByCat Array Controller” bind the Content Set (not the Array) to “CategoryView Array Controller.selection.expenses” this will cause the array controller to be filled by the expenses of the currently selected category.

ExpenseByCat Binding

Now that the array controller is hooked up we need to bind the table view columns. Bind each column to “ExpenseByCat Array Controller.arrangedObjects” and set the “Model Key Path:” as needed for each column.

Expense Table Bindings

Then select that placeholder label that you put below the table view earlier and bind it the same as the table view columns (“ExpenseByCat Array Controller.arrangedObjects”) for the “Model Key Path:” though you are going to enter a little magic: “@sum.amount” this will take care of adding up all the amounts of each expense in the category for you.

sumBinding

Build and Go!

CategoryRunningExpenseRunning

You should be able to add and remove Categories and Expenses. Undo should already work. Saving and reverting should work. So should the total for each category, that’s a lot of stuff with out writing any code yet! But there are some things that would be nice to add.

In the next installment we will add:

  • New expenses default to the current date.
  • Alphabetize categories in the popup menu.
  • Make expenses start out sorted by date and keep them that way even when the date is edited.
  • Copy and paste of expenses.

Let me know what you think or if I missed something (after all I am still fairly new at this). Also if you have any ideas about how to sort out how much was spent in each category for each month please let me know.

20 Responses to “A Core Data Tutorial Part 1”

  1. Resources: Core Data at Under The Bridge Says:

    […] And there's a new tutorial series starting here that looks worth following as […]

  2. Stream Says:

    Just nothing to add 🙂 It’s a wonderful tutorial! Thank you Mike!

  3. Andrew Says:

    The tutorial is very helpful. In terms of appearance, I’d just change the screenshots to use the full window capture in the screen grab utility. (cmd-shift-4, followed by a tap on the spacebar) You’ll get only the window, with drop shadows, etc.

    Keep it up though!

  4. n-rd » Blog Archive » Coredata tutorial Says:

    […] theMikeSwan: Coredata tutorial […]

  5. Doug Says:

    This is a great tutorial. I mainly develop in the Windows environment and am new to Objective C and Cocoa. Once you get your head wrapped around the idea of IBOutlet’s and IBAction’s, the rest is pretty easy.

    With that said, there is one area that I’m not really used to, or perhaps just don’t understand. For example, one can write out bits and pieces of code in the watch window in Visual Studio, like: isSomething == toThisVariable and it will print out in the watch window the result or do what ever other calculation.

    Other than that, Xcode is pretty cool.

    • themikeswan Says:

      I’m not sure I fully understand your comment, but I think you may be looking for NSLog(). You could for example do something along the lines of: if (isSomething == toThisVariable) NSLog(@”isSomething == toThisVariable”); else if (isSomething != toThisVariable) NSLog(@”isSomething != toThisVariable”); There is likely an easier way to do this that I have not thought of yet but you get the idea I hope. I use NSLog() a great deal when first working on a new bit of code to see how things are going.

  6. coder Says:

    Do you have a similar tutorial to build in iPhone environment ?

  7. Rolf Says:

    I just want to thank you for taking the time to create this example and share it. I am a seasoned programmer, but I’m new to Mac development. I find the binding options in IB very complex, and your example help me to stop over complicating the situation. For example: I had bindings for both the TableView and the columns in my application, which caused some very odd behavior in the code. Anyway, thank you again!

  8. Tony Says:

    Hi Many thanks for this tutorial – have used your example on another program (my own personal training) which is working fab

    if I was to add a button next to the amount field and if clicked would put ‘500’in the amount field – how would I do that ?

    best Regards

    • themikeswan Says:

      I haven’t ever tried anything like this, but I would start by making an IBOutlet for the amount field and an IBAction too set the field to 500. [amountField setFloatValue: 500.0]; or if you were looking to increase the amount by 500 [amountField setFloatValue: ([amountField floatValue] + 500)]; Both of these methods should cause the model to get updated.

  9. Richie Says:

    Great tutorial! I’ve looked at others included the ones you mentioned but the one you’ve done just clicked.

  10. Clint Mc Says:

    Great tutorial, thank you! Just a quick question, is there a way to pre-populate the array controller with some Category objects?

    For instance lets say I wanted to have some default categories such as Housing, Bills, Savings, etc that were available as defaults upon startup. Is that possible?

  11. Mario Says:

    Thanks a lot!

  12. Christer Bernérus Says:

    Have you tried this in Xcode 4? I did and found myself stumbling in the dark when I got to the point where the tutorial says “drag over a Core Data Entity from the IB Library”
    Where’s the IB Library? Is it an XCode 3 thing or am I just too new to this ?

    • themikeswan Says:

      The library is in the lower right corner of the window. You may have to open it and/or select the library instead of one of the other options, like the code snippet library.
      However, at the moment they have removed the ability to quickly generate a prototype UI (I just spoke to an Apple engineer from the Xcode team and he was unaware of any new location for the option but wasn’t sure). You can of course manually add all the interface items and bind them on your own. This method does suck a bit and I have filed a bug for it Radar # 9591386.
      When I get a chance I will update the tutorial for all the added steps.

  13. Joe Says:

    I too tried this and fell over at the same part as Christer. It would be great if you could do an XCode 4 re-run. Other than that, it looks like a fantastic beginner’s tutorial!

  14. Plucker Says:

    +1 for the Xcode 4 version please!

  15. Paul Says:

    Wonderful. Thanks a bunch for sharing your knowledge.

  16. amarsawant Says:

    Reblogged this on myBlogs.

Leave a reply to n-rd » Blog Archive » Coredata tutorial Cancel reply