Start learning with our library of video tutorials taught by experts. Get started
Viewers: in countries Watching now:
The iOS software development kit (SDK) includes the popular SQLite library, a lightweight yet powerful relational database engine that is easily embedded into an application. In this course, Bill Weinman teaches you how to build an RSS reader for iOS devices, integrating XML data and a streamlined interface. He explains how to use the SQLite database, display information in a table view, code view controllers, and create a preferences pane for your app. The resulting application is optimized for all iPhone and iPad displays.
Now that we have a working table view, we need to bring in our database library, so we can display the feeds in our main view. We'll start by making a working copy of the BWRSS project from earlier in this chapter, or you can copy from my BWRSS-02-done, like I'm doing here, and I'm just going to rename that to BWRSS-03-working. I'm going to open into Xcode by double clicking on the Xcode project file. And the first thing we need to do is we need to load in the libraries that we're going to be using.
We're going to start by loading in the SQLite Framework so I'm going to select the Target here and Summary and scroll down to where we have the Linked Frameworks, press the plus button and type in sqlite and select sqlite 3.dylib, which stands for Dynamic Library. And I'll click Add, and that adds in the dynamic library here. Now I'm going to bring in the libraries from the exercise files so we'll come back over here to the finder and under Exercise Files in Libraries, I am going to select all three of these BWDB, BWUtilities, and RSSDB--I'm just holding down the command button on the keyboard while I select those. And I'm going to drag all of those into our BWRSS folder here in our project, and when I let go over that, you'll see we get this dialog box in Xcode.
I want to make sure Copy items is checked, Create groups is checked, and the target BWRSS is checked. And I'll select Finish, and it copies those libraries in. Finally, coming back out here to the libraries folder in finder, I'm going to grab this BWRSS.db file, this is the starting point database that we created in our previous chapter, and I'm going to drag that into our project as well, and I'm going to make sure Copy items and Create groups and the target are checked and press Finish, and there we have database as well now.
So now we'll come into our header file, and I'm going to import RSSDB.h header file and press Command+S to Save. And I'm going to come over here in our View Controller and up here in this interface section here, this is where we declare local object variables, and I'm just going to remove this objects variable, and I'm going to come in here and add some other variables. We'll have a BOOL for iPadIdiom, and that'll be a logical variable for checking if we are on an iPad or a non-iPad iPhone.
A dictionary object, NSDictionary, and we call this newFeed, and I'm using the underscore for a lot of these, because that's convention for instance variables in Objective-C and RSSDB, this will be our database object and then an array for the feedIDs. We'll make a little space there, press Command+S on my keyboard to Save my progress so far. Now we're going to add database support. First of all, I want to point something out here, we'll get to this a little bit later.
You notice these red lines that have appeared down here. That's because I deleted that object variable, and you notice that that's used throughout here. We're going to get to that and clean that up in a minute. First I want to bring the database support, and that comes in from Chapter03, this file here, there's a text file here with a bunch of Objective-C code in it. Objective-C code tends to be a little bit verbose, and so, rather than type a lot of this stuff, and there's quite a bit of it, we're just going to copy and paste it. So starting there and coming down to just before where it says view methods here on line 52, so I'm going to select all the way down to line 51, I'm going to press Command+C to Copy and come back in here to Xcode, I'm going to go all the way down here to the end of the file just before where it says end, put my cursor right there and press Command+V to Paste.
So that end needs to be at the end of the file, and I've got all of this code that I just added before that. That's our database methods, and we'll be looking into that a little bit more later. Now let's come up here to where some of these errors are, insertNewObject. We don't need that anymore, because that objects instance variable was just there as part of the template for the table view application. numberOfRowsInSection, we can find that also in our text file over here. I'm just going to grab that and copy that and paste it in here, and scrolling down cellForRowAtIndexPath, we're going to update that a little bit.
I'm just going to delete these two lines for now. We'll be getting back to this. And finally, this whole commit editing style, we don't need any of that, I am just going to delete that whole thing. Now I'm going to press Command+S to Save, and I'm just going to press Command+B on my keyboard here to Build and make sure that this compiles, and you see the Build Succeeds, and there aren't any issues. So that's a good sign so far. Now we've got just a few more things we need to do in order to inform the table view about the data so that the table view can display the data.
There's a function in here called awakeFromNib, and see I can select from this little selector up here, it's a convenient feature of Xcode. And we're not going to be using that because we're not using a nib, we're using storyboards instead, so I'll delete that method. Under viewDidLoad, there's just another line we want to add in here to display the edit button in the navigation bar, and it look likes this, self.navigationItem.leftBarButtonItem = self.editButtonItem, and that will display that edit button item in the navigation bar, and I want to add a viewWillAppear method, and we can find that again in our text file here.
Right there, I'm just going to grab that and copy it and paste it into our Xcode. I'm just going to put it right here before this pragma. And so when the view is just about to appear, it checks to see if our current device user interface idiom is the iPad, and if so, it sets a little iPadIdiom flag to Yes. Then it calls loadFeedIDs and reloadData on the table view. LoadFeedIDs is our own method down here. We come down here into our database stuff, and you see it's very simple, it simply checks to see if we have a database, and if not, loads the database.
That loadFeedDB will alloc and init the database right there. And then once it has the database, it comes up to our feedIDs variable, and it loads that by getting all of our feedIDs from the database. And so what we end up with is this array, and if we come up here to the top we can see our instance variable that says NSArray of feedIDs and is an array of the IDs of the individual feed items, that are going to be displayed in the table view. Now if we come down here to number of sections in table view, that's always going to be one, because we only have one section and number of rows and section, of course, we've loaded that already, and that is the count of the number of feedIDs.
And so finally, this cellForRowAtIndexPath, that's where the actual cell is populated, and before we can do that, I'm going to press Command+S to Save what we've done so far. We're going to go in to our iPhone storyboard. That's this one here, and we just need to set up this table cell a little bit. So I'm going to scroll that over, and I'm going to bring up our Inspector, and I'm going to make sure I select the Attributes Inspector, which is this one here. The Table View Style is going to be Subtitle, and we need an Identifier for it.
That Identifier is going to be FeedsCell, and I'm just going to select it and press Command+C, put it in my copy buffer, because we're going to need that in just a moment. And then I'm going to come down here where it says Accessory, and I'm going to select None, because we don't need a disclosure arrow for that. So I've got my main storyboard selected over here, I'm going to press Command+S, and you see that that now is showing saved, I'm going to get rid of the inspector pane and come back over here to our FeedsTableViewController, and you'll notice where it says cellForRowAtIndexPath method, and you notice that it says dequeuReusableCellWithIdentifier, and it says Cell, I'm just going to select that and past that FeedsCell string.
These need to be exactly the same, and it's really easy to misspell it--and I've on occasion I've forgotten the S or something--and that creates an error. I'll show you later on what that error looks like in case you actually get it. So makes sure that we're using this particular style. So here we have a style that's got the subtitle style. Pressing Command+S again, that was showing it wasn't saved. And so it's making sure that it's using the correct table cell from the storyboard. Now we want to actually load our data here, and so what happens is each time a table cell is populated, the iOS system will call this function in your application, and it will pass you an index path that tells you which cell it is that it's populating.
So we need to take that index path and use it to find the correct data from our database. Okay? And so first, I'm going to make sure that I've loaded the FeedIDs, so I'm going to say self loadFeedIDsIfEmpty, then I'm going to Configure the cell. So I need a dictionary item for the feedRow itself, and I'm going to load that from the database. So I'm calling getFeedRow on the database and the row is this FeedIDs sub indexPath.row.
The indexPath.row, that's the particular row in the table that's being populated. And I use that to index into our array of FeedIDs, and that will give me the correct FeedID which I can pass to get feedRow. And that will give me the dictionary entry that I can load here, and now I've got the data all loaded into my NSDictionary object, and I can use it. I can say cell.textlabel.text = feedRow title, and I can say cell.detailTextLabel.text = feedRow description.
Now when I save this, I'm pressing Command+S on my keyboard, and I make sure I've got iPhone Simulator selected there, and I press Run, Build Succeeded, that's a really good sign. Now it loads up the simulator, and there it's displaying the data from our database in that table view. So these are the entries that we loaded up in the database in our previous chapter, the one we populated the database from the SQL schema. So now we have a working table view for our main page. I just want to show you one more thing.
If we come back here into Xcode, and I'm going to press Command+Period, and that will stop--and you'll see it says Finish running-- that stops the app from running on the simulator, and I'm just going to misspell this FeedsCell identifier, so you can see what happens. It's a really cryptic error, and if you get this, I want you to know what it means. So I'm just going to misspell that, I'm going to press Command+S to Save, and I'm going to press Run up here, and you notice that instead of running, it gives us this error. It switches us into Debug View over here in the navigator pane, and it gives us our console down here, and you'll notice that there is just a whole bunch of junk showing there in the output.
If you scroll up to the top, you see that there's an assertion failure, and it's in this table view, dequeueReusableCellWithIdentifier for IndexPath, and you'll notice that if we scroll down some more, it says uncaught exception and right over there, reason: unable to dequeue a cell with identifier xFeedsCell. And so, the error is buried in there, you got a bunch of stuff before it and a bunch of really pointless cryptic stuff after it. But if you look through there carefully enough you'll find what your error is.
And if we come back over here to the Project Navigator and select our Table View Controller, we see there is that string xFeedsCell, so if I spell that correctly, it'll make it work. So I'm saving with Command+S and pressing Run, it says it's already running, it's actually crashed, but that's okay, I'm going to click Stop, Build Succeeded, and there we have it running properly. We can minimize this also with that button there.
Just so you know when you see that error, that's what that means. So now we have a working table view for our main page. We're reading feeds from the database successfully. We're formatting them nicely in our table cells and displaying the data in the table view. This is the foundation of our application, and we'll be using this and building upon it for the rest of the course.
Find answers to the most frequently asked questions about iOS SDK and SQLite: Building Data-Driven Apps.
Here are the FAQs that matched your search "":
A: The RSSDB library had to be updated to work around a bug in the iOS 7 SDK.
There is a bug in the iOS 7 SDK that prevents the BWDB fast enumeration implementation from working on a device. The symptom is code that runs fine on the emulator, but not on a device. iOS devices use an ARM processor, while the emulator runs on your Mac's Intel processor. This points to the LLVM ARM code generator as the source of the bug. Because the bug appears to be in the LLVM compiler, it may be some time before it is fixed.
As a workaround we have changed the getFeedIDs and getItemIDs methods in the RSSDB library so they don't use Objective C fast enumeration.
Please note that this same bug also affects some of the BWDB testbed code in Chapter 2. The result is that it will run on the emulator but not on a device.
"Used type va_list (aka_builtin_va_list) where arithmetic or pointer type is required"
Sorry, there are no matches for your search ""—to search again, type in another word or phrase and click search.
Access exercise files from a button right under the course name.
Search within course videos and transcripts, and jump right to the results.
Remove icons showing you already watched videos if you want to start over.
Make the video wide, narrow, full-screen, or pop the player out of the page into its own window.
Click on text in the transcript to jump to that spot in the video. As the video plays, the relevant spot in the transcript will be highlighted.