iPhone Life magazine

Unleash Your Inner App Developer Part 17: Core Data Test Drive

Do you have an idea for an app but lack the programming knowledge to begin building it? In this weekly blog series, I will take you, the non-programmer, step by step through the process of creating apps for the iPhone, iPod touch, and iPad. Join me each week on this adventure, and you will experience how much fun turning your ideas into reality can be! This is Part 17 of the series. If you are just getting started now, check out the beginning of the series here(This post has been updated to iOS 7.1.)

In my previous post, you learned how to generate Objective-C classes from entities in a data model and you were introduced to the mmBusinessObject class, which provides an easy-to-use wrapper for Core Data classes. In this week's post, we're going to create our app's custom business controllers and take them for a test drive!

In order to perform the steps outlined in this post, you can get the latest version of the iAppsReview project at this link. I recommend following the steps in this post yourself, but if you get stuck, you can get the finished app at this link.

Creating Business Controllers

By way of reminder, Figure 1 shows the three business controllers we need to create for the app, and all three will be subclasses of the ABusinessObject class.

Business controller classes
Figure 1 - The business controller classes are subclasses of ABusinessObject.

Creating the Review Business Controller

First, let's create a Review business controller object.

  1. Open the iAppsReview project in Xcode;
  1. In the Project Navigator, right click the AppCategoryEntity.m file (so the new files are added directly below AppCategoryEntity.m), and select New File... from the popup menu;
  1. On the left side of the New File dialog under the iOS section, select Cocoa Touch. On the right side of the dialog, select the Objective-C class template, and then click the Next button (Figure 2);
Create a new class
Figure 2 - Create a new Objective-C class.
  1. In the next step of the dialog, set the Class to Review and set Subclass of to ABusinessObject as shown in Figure 3;
Create Review class
Figure 3 - Create a Review class subclassed from ABusinessObject.
  1. Click the Next button to launch the Save File dialog. Click the Create button, which adds the new Review classes to the Project Navigator as shown in Figure 4;
New review class files
Figure 4 - The newly added Review class files
  1. Now let's add an init method to the Review class that allows us to specify the name of the associated entity class.

In the Project Navigator, select the Review.m file and add an empty line between the @implementation and @end declarations;

  1. Type the init keyword to bring up the Code Completion popup (Figure 5);
The init Code Completion popup
Figure 5 - The init Code Completion popup
  1. Press return to add the init code template to the file as shown in Figure 6;
Figure 6 - The init code template
  1. Replace the statements placeholder with the code shown in Figure 7 (you can just start typing to replace it).
Set entityClassName
Figure 7 - Set the entityClassName property.

This code sets ReviewEntity as the default entity class associated with the business controller. This allows you to avoid typing the entity class name every time you want to create, retrieve, update, or delete a ReviewEntity.

Creating the AppCategory Business Controller

Now let's create an AppCategory business controller. The instructions are very similar to those in the previous section, so I'll abbreviate them a bit. 

  1. Right-click the iAppsReview.xcdatamodeld file in the Project Navigator (so the new files are added directly below it), and select New File... from the popup menu;
  1. On the left side of the New File dialog under the iOS section, select Cocoa Touch. On the right side of the dialog, select the Objective-C class template, and then click the Next button;
  1. In the next step of the dialog, set the Class to AppCategory and set Subclass of to ABusinessObject (it should already default to ABusinessObject since this dialog remembers the last value you specified);
  1. Click the Next button to launch the Save File dialog. Click the Create button to add the new AppCategory class files to the Project Navigator as shown in Figure 8;
New AppCategory class files
Figure 8 - The new AppCategory class files
  1. Now let's add an init method to the AppCategory class. Select the AppCategory.m file in the Project Navigator, and add an empty line between the @implementation and @end declarations;
  1. Type the init keyword to bring up the Code Completion popup, and then press return to add the init template code to the file;
  1. Replace the statements placeholder with the code shown in Figure 9.
Set the AppCategoryEntity class name
Figure 9 - Set the entityClassName property of the AppCategory class.

Again, this specifies the name of the entity class associated with the business controller.

Creating the User Business Controller

Now let's create our final class, the User business controller.

  1. Right-click the ReviewEntity.m file in the Project Navigator (so the new files are added directly below it), and select New File... from the popup menu;
  1. On the left side of the New File dialog under the iOS section, select Cocoa Touch. On the right side of the dialog, select the Objective-C class template, and then click the Next button;
  1. In the next step of the dialog, set the Class to User and set Subclass of to ABusinessObject;
  1. Click the Next button to launch the Save File dialog. Click the Create button to add the new User class files to the Project Navigator as shown in Figure 10;
New User class files
Figure 10 - The new User class files
  1. Now let's add an init method to the User class. Select the User file in the Project Navigator, and add an empty line between the @implementation and @end declarations;
  1. Type the init keyword to bring up the Code Completion popup, and then press return to add the init template code to the file;
  1. Replace the statements placeholder with the code shown in Figure 11.
Set the UserEntity class name
Figure 11 - Set the entityClassName property of the User class.

This specifies that UserEntity is the name of the entity class associated with the business controller.

Using Business Controllers with View Controllers

When you place all of your entity manipulation code in business controllers, you create an app architecture that is easier to conceive, create, and maintain. In order to use the code within these business controllers, you need to instantiate them from within your app's view controllers and pass messages to them that create, retrieve, update, and delete entities.

Figure 12 shows the collaboration between view controllers and business controllers.

View Controllers and Business Controllers
Figure 12 - View controllers can call on the services of business controllers to manipulate entities.

The grouping of view controllers and business controllers you see in this figure is actually what you are going to set up in this post and upcoming posts. Note that although the diagram only shows one business controller referenced from each view controller, a single view controller can work with multiple business controllers.

Setting Up the App Category Scene

As promised earlier in this blog series, we are going to take the iAppsReview prototype app and turn it into a real app. We'll start with the App Category scene since it's an easy one.

Currently, the App Category scene contains a hard-coded list of categories that you added when you first created the project (Figure 13).

App Category Scene
Figure 13 - The App Category scene

Rather than having a hard-coded list of categories, we want to change this scene so the categories are populated from a list of CategoryEntity objects stored in the database and dynamically retrieved at run time. This allows us to add new categories to the list in the future without changing the app. Let's get started!

  1. In the Project Navigator, select the MainStoryboard file and then scroll the storyboard so you can see the App Category scene;
  1. As shown in Figure 13, this scene has a table view that contains nine prototype cells that all have the same formatting. We only need one cell that will be used as a prototype for all cells in this table, so let's delete the last eight cells in the table view.

To do this, click the second cell in the table view to select it, hold down the shift key and click on the third through ninth cells to select them too;

  1. With these cells selected, press the delete key to delete the cells and leave the first cell remaining as shown in Figure 14;
Delete all cells but the first
Figure 14 - Delete all but the first App Category cell.
  1. In the App Category scene, click in the gray area below the table view. Go to the Attributes Inspector (third button from the right in the Inspector toolbar) and change the Content attribute from Static Cells to Dynamic Prototypes. Doing this adds a Prototype Cells header label above the table view (Figure 15).
Dynamic Prototypes
Figure 15 - Set the table view's Content to Dynamic Prototypes.

Header labels are used to describe the contents of a table view, but since the navigation bar already contains the text App Category, there's no need to use the header label. You can simply ignore the header label and it won't appear at run time;

  1. Click on the Entertainment table view cell to select it, and then go to the Attributes Inspector and set the cell's Identifier to CategoryCell (Figure 16).
Cell Identifier
Figure 16 - Set the cell's Identifier to CategoryCell.

This identifier allows you to reference this specific cell from code within your view controller, which we will create next.

Creating an AppCategoryViewController

Now we need to create a table view controller for the App Category scene. This table view controller will create an instance of the AppCategory business controller and fill the table view with AppCategoryEntity objects.

  1. Right-click the iAppsReview group folder in the Project Navigator, and select New File... from the shortcut menu;
  1. On the left side of the New File dialog under the iOS section, select Cocoa Touch. On the right side of the dialog, select the Objective-C class template, and then click Next;
  1. In the next step of the dialog, set the Class name to AppCategoryViewController, and set the Subclass of to UITableViewController (Figure 17);
Create AppCategoryViewController
Figure 17 - Create AppCategoryViewController as a subclass of UITableViewController.
  1. Click the Next button to display the Save File dialog, and then click Create to add the new AppCategoryViewController class files to the project (Figure 18);
New AppCategoryViewContoller files
Figure 18 - The new AppCategoryViewController class files
  1. Whenever you create a new view controller for a particular scene, it's a good idea to immediately go to that scene and associate it with the scene. 

To do this, go to the Project Navigator, select the Mainstoryboard file and then click the status bar at the top of the App Category scene to select the table view controller. You will know you have selected it properly when a blue highlight appears around the scene as shown in Figure 19. Next, go to the Identity Inspector (third button from the left in the Inspector toolbar) and change the class to the new AppCategoryViewController;

Set the view controller class
Figure 19 - Set the App Category view controller's class to AppCategoryViewController.
  1. Let's go back and set up the AppCategoryViewController class. Select AppCategoryViewController.m in the Project Navigator, and add the import statements shown in Figure 20 to the top of the file.
import statements
Figure 20 - Add import statements to the AppCategoryViewController.m file.

These import statements allow you to create an instance of the AppCategory business controller and work with its associated AppCategoryEntity objects;

  1. Next, add the instance variable declarations shown in Figure 21 below the @implementation declaration (don't forget to add the curly braces).
instance variables
Figure 21 - Add instance variables to the class.

The appCategory variable will be used to hold a reference to the AppCategory business controller object, and the appCategoryList array will be used to hold the AppCategoryEntity objects returned from the business controller;

  1. In the view controller's viewDidLoad method, delete all of the existing comment lines (the lines in green) and add the code shown in Figure 22 in its place.
viewDidLoad code
Figure 22 - Add code that creates an AppCategory object and retrieves a list of AppCategoryEntity objects

This code creates an instance of the AppCategory business controller class, and then sends a getAllEntities message to it, storing the resulting entities into the appCategoryList array. As its name suggests, this method returns all entities of a particular type. The AppCategory class (as well as all of your other business controller classes) inherits the getAllEntities method from the mmBusinessObject class. Rather than having to type several lines of code (as you would have to do with out-of-the-box Core Data), you only need one line of code to retrieve the CategoryEntity objects. This is the beauty of object-oriented inheritance and encapsulation!

  1. Now it's time to change the methods of the table view controller that are used to fill the associated table view in the App Category scene. In a future post I'll discuss table view controllers in greater detail, but for now I'll just give you the information you need to know to understand the basics.

Scroll down to the numberOfSectionsInTableView: method. This method is used to specify the number of sections in the table view. Delete the line that begins with #warning. Since this table view only has one section, change the method to return 1 as shown in Figure 23;

Number of sections
Figure 23 - The numberOfSectionsInTableView: method specifies the number of sections in the table view.
  1. Scroll down to the numberOfRowsInSection: method. This method specifies the number of rows in a particular section of the table view. Delete the #warning line and change the return statement to the code shown in Figure 24.
Number of rows
Figure 24 - The tableView:numberOfRowsInSection: method specifies the number of rows in a section of the table view.

Since there is only one section in this table view, we don't have to check the section number that is passed to this method. The code you have added returns the number of AppCategoryEntity objects in the appCategoryList array. This causes the table view to create one row for each entity object in the array;

  1. Now scroll down to the tableView:cellForRowIndexPath: method. Uncomment this method by deleting the /* comment characters above it and the */ comment characters below it. Change the code in this method to the code shown in Figure 24.
cellForRowAtIndexPath
Figure 24 - tableView:cellForRowAtIndexPath configures the rows in the table view

This method gets called once for every AppCategoryEntity in the appCategoryList array. The first few lines of code send a message to the table view asking it for a cell with the CategoryCell identifier. This is the identifier you specified for the remaining cell in the App Category scene earlier in this post. The table view returns the prototype cell with that identifier.

Next, this code gets the AppCategoryEntity in the appCategoryList with the specified row number. In Objective-C, collections are numbered starting with zero. So, a collection with 10 items would be numbered 0 through 9. The first time this method is called, a zero value is passed in as the row number. That zero value is then passed in the objectAtIndex: message call to the appCategoryList and the first  AppCategoryEntity object in that array is returned. The next time the method is called, a 1 is passed in the objectAtIndex: message call and the second AppCategoryEntity in the list is returned, and so on.

After an entity is retrieved, its name value is stored in the cell's main text label, and the cell is returned from the method;

  1. Now that the setup of the App Category scene is complete, it's time to run the App to see what it looks like at run time. To do this, click the Run button in Xcode. When the app appears in the Simulator, select Write a Review and then in the Write Review scene, click the App Category row and you will see the App Category scene shown in Figure 25.
Empty App Category list
Figure 25 - The App Category scene is empty!

You may be surprised to see that there aren't any rows in the table view! That's because we never created a database and added any records to it. 

Conclusion

When your app first tries to access a database, if it doesn't exist, Core Data automatically creates an empty database for you. In next week's post, we'll take a close look at this database, and then we will add CategoryEntity objects to it and see how they fill the list at run time!

<<Previous          Next>>

Want to master your iPhone and iPad? Sign up here to get our tip of the day delivered right to your inbox.
Email icon
Want more? Get our weekly newsletter:
Kevin McNeish's picture
Kevin McNeish is author of the new "iOS App Development for Non-Programmers" book series (www.iOSAppsForNonProgrammers.com), winner of the 2012 Publishing Innovation Award. Kevin is also an award-winning app developer, software architect, and well-known software conference speaker in the U.S. and abroad. He has spent much of his career making difficult concepts easy to understand for the uninitiated. Follow Kevin on Twitter: @kjmcneish.