By Kevin McNeish on Thu, 08/27/2015
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 22 of the series. If you are just getting started, check out the beginning of the series here. (This post has been updated to Swift 1.2, Xcode 6.4, and iOS 8).
In the last few posts in this series, you have learned a lot about retrieving entities from a database using Core Data, and displaying the results in a table view. Now that we have we have all the other functionality working in the Write Review scene of iAppsReview, it's time to learn how to save a ReviewEntity using Core Data!
In order to work through the steps in this post, you can use the iAppsReview project you have created so far. If you need a fresh copy of the project, you can download it at this link.
As I have mentioned in the past, saving entities to a database is easy to do—especially when you are using the mmBusinessController wrapper class. Let's take a closer look at this class to learn more about how entities are saved.
- Open the iAppsReview project in Xcode.
- Go to the Project Navigator, expand the Business Layer group, and then click on the mmBusinessObject.swift file to open it in the Code Editor.
- Let's find the saveEntities method. When you have a large code file with many methods, the easiest way to do this is to use the jump bar at the top of the Code Editor. As shown in Figure 1, click the very last section of the jump bar.
|Figure 1 - Click the last section of the jump bar.|
- In the popup list that appears when you click the jump bar, select saveEntities as shown in Figure 2.
|Figure 2 - The jump bar popup list|
Selecting this method in the popup list takes you to the place in the code file where the method is located as shown in Figure 3.
|Figure 3 - The saveEntities method|
Let's take a closer look at this code. The first line of code declares a few local variables. The next line of code gets a reference to the business controller's object context. As you learned in a previous post, the object context keeps track of all entities that are retrieved from the database as well as any newly created entities. It tracks all changes that are made to these entities, and can save all changes to entities in the database on an iOS device.
The next line of code is shown in Figure 4.
|Figure 4 - The main messages passed to the object context to save entities|
This code first calls the hasChanges method on the object context. If this method returns false, the save is aborted (because in Swift, the && operator doesn't evaluate the right-hand condition if the left-hand condition is false.)
If the hasChanges method returns true, then the save: method is called on the object context. This causes the object context to save changes to all new and edited entity objects.
As an aside, you may be wondering about the ampersand (&) in front of the error parameter. Normally in Swift, the value of an argument is passed in a method. However, if you preface the argument with an ampersand, a pointer to the argument is passed. It's passed this way so that the save: method can modify the value of the error argument and the new value is available to the calling method.
If the method returns false, the first set of code in curly braces executes. The error information is stored in the saveState and saveMessage variables and these values are returned to the caller. If all goes well and the save: method returns true, the method sets the values of the saveState and saveMessage variable indicating the save was successfully completed, then returns those values to the caller.
Creating a New Entity
In the Write Review scene of the iAppsReview app, we have to perform the following steps when the user clicks the Post button:
- Create a new ReviewEntity object.
- Get the values from the user interface controls 2 store them in the properties of the ReviewEntity object.
- Save the ReviewEntity object.
- Post the review on the web (we'll get to this later in this series).
The mmBusinessObject class has a createEntity method that we can use to create a new ReviewEntity object. Let's take a look a behind-the-scenes look at this method.
Click the far right segment in the Code Editor jump bar, and select createEntity from the list (Figure 5).
|Figure 5 - Select the createEntity method.|
You should now see the createEntity method code shown in Figure 6 (I have broken the code into three separate lines to make it easier to read.)
|Figure 6 - The createEntity method code|
The code in this method calls the insertNewObjectForEntityForName:inManagedObjectContext: method on the NSEntityDescription class. This method accepts two parameters. The first is the name of the entity class (we just grab this off of the business controller object) and a reference to the object context (which we also grab from the business controller.) An object of type T is returned from this method, and it is simply passed back from the createEntity method. In this code sample, T is a generic placeholder for a more specific type of entity object. We'll be talking more about generics later in this series!
In object-oriented terminology, we call this a factory method because it manufactures, or creates objects.
The code in this method is standard, boiler-plate Core Data code. I want to impress this fact on you so that you know that when you use the mmBusinessObject class, you are really using standard Core Data code.
Implementing the New and Save Code
Now that you understand the basics of how to create and save entities, let's implement this code in the iAppsReview project.
- In the Project Navigator, select the WriteReviewViewController.swift file to display it in the Code Editor.
- Use the Code Editor jump bar to select the postReview: method.
- You should see the postReview: method code shown in Figure 7.
|Figure 7 - The postReview: method code|
As it turns out, I have already implemented the necessary code for you! We tweaked this code in my previous post without taking too close a look at it.
The first line of code creates a new ReviewEntity object. The next several lines of code grab values from the various user interface controls and store then in the properties of the ReviewEntity object. Next, the saveEntities method is called on the Review business controller, which saves the new entity in the database. Finally, a popViewControllerAnimated: method is called on the navigation controller, which causes the app to navigate back to the main iAppsReview scene.
Testing the Code
Now it's time to take the code for a test drive.
- In Xcode, click the Run button.
- When the app appears in the Simulator, click the Write a Review option.
- In the Write Review scene, select an App Category and rating, and enter an App Name, and comments. When you do this, the Post button should become active as shown in the example in Figure 8. Remember that you can click the background of the scene to hide the keyboard!
|Fig 8 - The Post button is enabled.|
- Click the Post button. The code in the postReview: method executes as evidenced by the fact that the app navigates to the main iAppsReview scene.
So how do you know if the review was saved to the database?
Your Homework Assignment
My goal with this blog series is to teach you to write apps on your own. A real test of your ability is to write some code without training wheels. With that in mind, I have a homework assignment for you.
The My Reviews scene in iAppsReview is intended to display the reviews you have saved on your iOS device. Currently, this scene is still a prototype, displaying static review information. Your assignment is to convert My Reviews to a fully functioning scene that retrieves reviews from the database and displays them in a table view. Everything you need to know about retrieving and displaying entities in a table view can be found in this post.
After you are finished with the My Reviews scene, I'd like you to move on to the Review scene. This scene is displayed when you tap a row in the My Reviews table view and displays the details of the review. To get this to work, you are going to have to pass a ReviewEntity object from the My Reviews scene to the Review scene. Everything you need to know about passing data between view controllers can be found in this post.
You can also look at the code in the WriteReviewViewController and AppCategoryViewController code files for hints on how to complete these tasks.
In my next post I'll provide the solution to this post's homework. You will find that working through these problems on your own will help you learn these fundamentals of iOS programming, and show you what you truly understand and where you need a little more help. Happy coding!
Top image credit: Alexey Boldin / Shutterstock.com