Core Data on the iPhone - Building a Simple RSS Reader
My project is moving along, I hope to hit some milestones in the next few days! For now, I wanted to talk about how I'm using Core Data, and build a simple RSS feed reader to demonstrate it's use...
First off, some handy resources:
- Cocoa Dev Central: A Good Overview
- Core Data Recipes App
- Troubleshooting Core Data
- Core Data Relationships
- Project Code on GitHub
Core Data is a HUGE topic. The resources above are one's that I've used to get up to speed. If you're new to it, I would read them over as well as download the Recipes app and dig through it. For this post I'll create a new project and use much of the code that I've already written from my existing iPhone app. I wanted to provide a complete project for everyone to download.
What I'm going over:
- Create a Project with Core Data
- Create the Database
- Fetch and Parse RSS feed
- Dump to Database
- Display to tableView
Let's get started...
1. Create A New Project
Make sure it's a Navigation Based Application and the checkbox "Use Core data for storage" is checked. What if you want to use a Tab Bar Application instead? I've just manually copied over the methods that are auto generated into another application type. Maybe there's a better way, but that's worked for me so far...
2. Create the Database
When we created our new project, a default data model was created for us. Under the Groups & Files pane in Xcode, find the Resources directory, and expand the MyCoreData.xcdatamodel directory. Single click the MyCoreData.xcdatamodel file and find a graphical respresentation of the default model.
The default setup is not going to work for us, so let's fix it!
First, we are doing to change the entity name to "Stories" by double clicking it and typing in the new name. Next we need to add some new attributes. Think of the entity as the table, and the attributes as the columns in a traditional database.
We are going to leave the timeStamp attribute and add title, summary, date and link. These will all be string types. Set it all up to look like this:
Now we have a model that represents the stories found in each RSS feed. You'll notice that the Stories entity has a class of NSManagedObject, we need to change that. Change it the same name as our entity.
We want to create a new Managed Object Class. Highlight the Stories entity, click on the File menu and select New File.
Once selected, click Next and make sure that the Target "MyCoreData" is checked.
Click Next, and finish the process with the defaults selected. You'll now have a new Stories model:Okay, almost done! Still with me?
Now, we've changed our entity name from Event to Stories. There is one spot in the code base that this is hard coded, and we need to change that. In the RootViewController.m implementation file, find the fetchedResultsController method. This is an auto generated method used with core data. Within that method you will find:
Which needs to be changed to:
Pro Tip: If you've run the application before changing the entity name, you will get errors when trying to run it now. The reason? The db stored on the iPhone simulator (or your actual devise) has an entity named "Event" and your codebase now references an entity named "Stories." To fix this, run the code base, let it error, in the simulator (or your devise) click the home button and get to the desktop. Find this app, and delete it. Now, stop the program from running and try to Build & Run the project again. This will force a new database onto the simulator (or devise) and it will match your code base.
Okay. We're all set! Let's grab some remote data and dump it to the database!
3. Fetch and Parse the RSS Feed
The RSS feed fetching is based off of this old tutorial. Some of the code in that post works, some doesnt. But I've copied the useful bit's into this example project. Below are the main methods utilized:
Okay, so the parseXMLFileAtURL is the main entry point we want to call from our viewWillAppear method:
And when it's done, we'll have an NSMutableArray named stores populated with a hash of results.
The focus of this post is on Core Data, so please download the example code and dig through the methods mentioned above.
4. Dump to Database
At this point we have a fully populated stories array. We want to dump that information to the database and then query it for display in a Tableview. Why dump it to the db and then query it? Well, in a real world application you'll want to fetch an RSS feed by popping a thread and showing an activity indicator to the user. While that data is being fetched on another thread, the user can navigate around the app without issue. Once the feed has been downloaded and dumped to the db, we can query it the next time a user navigates to our tableView. With that thought in mind...
We are going to modify the insertNewObject method that was auto-created for us. First, we'll call it once the feed is done:
Then we need to loop through all of the Dictionary objects within the array and dump it to the database.
Pro Tip: Debug your sqlite queries. In the Groups & Files pane of Xcode, expand the Executables directory and right click on the exectuable selecting Get Info. Select the Arugments tab and add the following: -com.apple.CoreData.SQLDebug 1
Close that window. Select Run -> Console from the Xcode menu, then Run & Build your project. You will now see all of the sqlite requests!
And if you review your Console output, you will find all of the RSS stories inserted into Core Data!
5. Display to tableView
We have a cellForRowAtIndexPath method created with our new project, but we need to gut that code and add our own. There's not much to it, we just want to query the database and display the RSS title for each tableView row displayed:
Simple!
If we had a TON of data, a better approach would be to query the data once, stuff it into an array, and the cellForRowAtIndexPath method could access the index of the array instead...
Conclusion
That was a long post! But it's really very simple to accomplish once you run through it a few times. The next steps would be to only add RSS feed stories that have not already been added, and then include the ability to edit them, maybe add notes, and the ability to delete them. Adding notes to each feed would be a great topic to dig into for using relationships in core data.
And for totally unrelated reading enjoyment:
After the computer receives and processes a digital image (in this case, a webcam snapshot), ultraviolet laser beams are fired at the photoluminescent screen to produce square pixels of glowing green light. Subtle gradations are created by controlling the timing of the laser shots and allowing the darker portions of the image to fade. The completed image gradually disappears as the glow of the screen grows dim.Thanks PinkTentacle!





