Ready to watch this entire course?
Become a member and get unlimited access to the entire skills library of over 4,900 courses, including more Developer and personalized recommendations.Start Your Free Trial Now
- View Offline
- Prototyping the app
- Coding and working with a testbed
- Creating an Objective-C interface for SQLite
- Designing a database schema
- Creating the view controllers
- Reading and writing to the database
- Parsing the RSS feed with NSXMLParser
- Updating the item view with feed items
- Implementing the pull to refresh gesture for iOS 6
- Creating a universal application with multiple views
Skill Level Intermediate
Parsing XML is a processor intensive operation and mobile devices tend to have limited processing power. Even though Apple continues to improve the specs of each iteration of their devices, in order to preserve the responsiveness that these devices are known for, we'll be doing our parsing in a separate execution thread. This ensures that we don't block the main thread, which could cause the user interface to freeze during parsing. Let's start by making a working copy of BWRSS-XML-03. I'm going to use the -done version here, and I'm just option dragging to make a copy and rename that to -04.
I'll open the project in Xcode by double-clicking on this Xcode project file. Now, remember we have this NSLog line, which says we have data, and that happens when we finish loading from the NSURLConnection. So, if I run this in the iPhone Simulator, I select the iPhone Simulator and click Run. When I click on one of these feeds, you'll notice we'll get a message down here in the log that says have data. Click on another feed, have data.
So, I'll go ahead and stop this from running in the Simulator by selecting Xcode and pressing Command+Period. I'm just going to minimize our log area down there. Now, we're going to bring in a whole bunch of code in our text editor, because it's just way too much typing for us to do here in this lesson. So, you'll see the file here TableViewController-04-NSXMLParser.txt. I'm going to open that in my text editor, I'm using TextWrangler here. I'm going to go ahead and select all of the file, you'll notice that there's just a whole lot of code in here, and we'll go through this, and we'll take a look at it.
We're going to do that in Xcode. So, I'm going to Copy that with Command+C and select Xcode. I'm going to come all the way down here to the end. I'm going to put this in just before the Error handling here, and I'll Paste that with Command+V and press Command+S to Save. So, if we look at what we've added to the file here, we have the NSLXMLParser delegate methods. So, the way this works is when we set up the Parser, we set our own class as the parser delegate and then the parser calls the delegate methods inside of our class at each step in the parsing process so that we can process the data.
We have a few little Utility methods, and we'll look at these. These mostly have to do with formatting dates and these error handlers were in there before. So, if we look at didStartElement, this is a parser delegate that's called at the beginning of each element in an XML stream. Basically, what we do at the beginning of an element, depending on the type of an element, if it's a container, we just set things up to start accumulating data, and if it's not on a container, then we decide what to do individually based on that. For instance, if it's the ChannelElement, we start setting up the feed and item objects.
If it's an ItemElement, then we know that we've completed the item before, and we can use the contents of that item to start populating the database. If it's one of our containerElements then we just start accumulating data. DidEndElement tells us that we've gotten to the end of the element and especially in the case of the containerElements, it tells us that we can start adding items to the list, because we've reached the end of a container and all of the content of that container that's been accumulated, we can start adding that to the Items List.
In particular, if we have one of these dateElements, so these are really just different names for the PubDateElement, but then we need to clean up the date format, and if we come down here into our Utilities and look at dateStringToSQLDate, of all these different possible formats that I've discovered in RSS Feeds, and I know that there's more. There are probably still some that don't work with this app, because they have these different date formats. They are supposed to use a standardized format for their dates, but everybody uses a different format, and I don't know why.
It's just annoying mostly, but this is how we deal with it. So, we parse in from these different dates, we use the built-in dateFormatter in iOS. It's the same as in OS X and then we simply format it into the standard SQL format for storing in the database. That makes it possible. Compare dates, it makes it possible to sort dates, because this is a really sensible format for computer processing. Now, especially for our containers whenever we find characters, we accumulate that and at different points in the process we say, okay, we're done with this chunk of data, and we'll go ahead and process it.
And if there is an error, then we call handleError on the main thread and of course, handleError is the same as we've used elsewhere in this application for, especially in the NSURLConnection methods. So, we come back up here to our Support methods, parseRSSData that sets up the NSXMLParser in a separate thread. You notice that we have to put all of this code in this autoreleasepool that's because it's running in the secondary thread, and this is the new syntax for doing this with ARC, Automatic Reference Counting, starting in iOS 5.
In our addItemsToList method, this is where we add items to the database. Now because we haven't set up our Table methods yet, we're not going to be displaying this on the screen. So, we're going to put in here an NSlog so that we can see when we actually have the parser data, because we're not going to be actually displaying it on the screen yet, because we haven't set up those methods yet for handling the table. We'll do that in the next movie. For right now we just want to say item and use that for the title.
We'll put the publication date in parentheses, and we'll put the URL in square brackets. I'm a big fan of copy and paste. We're going to use our constants for keying off the Item here, kItemTitleKey and kItemPubDate and kItemUrlKey. It's looking like it's got a little warning here. Ah, yes, typo.
Here we go and press Command+S to Save. Now, we need to come back here to connectionDidFinishLoading, and you remember we have this NSLogin there that says have data. I'm going to go ahead and take that out, and I'm going to uncomment this detachNewThreadSelector so that we can go ahead and run the parser in our secondary thread. So you see there's our call to parseRSSData as the selector getting passed to detachNewThreadSelector, Target:self, Object: self.rssData.
I'll go ahead and press Command+S, and we are going to Build, I'm going to press Command+B on my keyboard here and Build Succeeded. No problems. We can go ahead and run this in the iPhone Simulator. Now, when I click on one of these, you see down here we got our parsed data, and you can see here is item: On Choosing a Programming Language, that's the title, there's the publication date in the parentheses there.
Down here in the square brackets, that's the URL associated with that. So, I can go ahead and click on one of these other feeds, and you see we got a lot of data there for that feed. I can click on the final feed, and we get even more data. So, now we're successfully parsing the feed, and we're updating the Item Table in the database with the Items from the RSS Feed. At this point, all that's left to do is to update the TableView with the Items from the database just as we did with the feeds in the FeedsTableViewController.
So, I'll go ahead and quit the Simulator and minimize this and get ready for the next lesson.