iPhone Programming Tutorial - Creating a ToDo List Using SQLite Part 1
If you have been following my tutorials, you know that we have been working primarily with UITableViews. This is mostly because SO many applications can be developed using this simple control. This final UITableView tutorial will be taking all of the skills learned from previous tutorials, putting them all together, and adding SQLite to create a prioritized To-Do list. I will also be showing you how to add multiple columns to your table cells and we will be exploring some of the other controls that the iPhone has to offer. What good would the tutorials be if we didn’t use them to create something useful.
I will move a little faster in this tutorial while still explaining the new stuff in detail. I will assume that you have completed the fruits tutorial and it’s prerequisites.
This tutorial will be a multipart series as it will be a little longer than my previous ones. In this first tutorial, you will learn:
- Create a NavigationBased Application
- Create a Database
- Add the Database to Your Project
- Add the SQLite3 Framework
- Create a Todo Class Object
- Initialize the Database
So let’s get started…
Open up X-Code and Select File->New Project… Select Navigation-Based Application and click Choose…
Name your project todo. Now let’s create the todo database that we will be using. Open up the Terminal application on your Mac. This is located in Applications > Utilities.
If you have installed XCode, you should have mysqlite3 already on your computer. To check this, type:
sqlite3 into the Terminal and sqlite3 should start. Type .quit to exit. If sqlite3 is not installed, install all of the XTools from your Mac Installation Disk.
Now that the terminal is open let’s create the database. This is done with the command:
sqlite3 todo.sqlite
SQLite3 will now start and load the todo.sqlite database. By default the database is empty and contains no tables. If you need a refresher on the basics of SQL databases Google It. Since our application is fairly simple, we only need to create one table. We will create a table called todo by typing the following statement:
CREATE TABLE todo(pk INTEGER PRIMARY KEY, text VARCHAR(25), priority INTEGER, complete BOOLEAN);
One thing to note here is the pk field. It is the primary key of the table. This adds functionality such that every time a row is added to the database, it auto-increments this field. This will be a unique identifier to identify each row. All of the other fields should be fairly self explanitory.
Now that our table has been created, let’s add some data. We will eventually be adding todo items within our app, but for now we will add some defaults. Type the following commands below.
INSERT INTO todo(text,priority,complete) VALUES('Take out the trash',3,0);
INSERT INTO todo(text,priority,complete) VALUES('Do Computer Science homework',1,0);
INSERT INTO todo(text,priority,complete) VALUES('Learn Objective C',1,0);
INSERT INTO todo(text,priority,complete) VALUES('DIGG this tutorial',2,0);
You can add as many todo items as you would like. For this tutorial, make sure you enter a priority between 1 and 3 (You’ll see why later). Now our database has been created and populated let’s exit out of SQLite3. Do this by typing .quit. Your terminal window should look something like this.
Now go back to XCode. Do a Control-Click (right click) on the folder named Resources. Click Add -> Existing Files… and browse to your todo.sqlite file and click Add. It will then prompt you with a screen like this.
Make sure you check the box that says Copy items into destination group’s folder (if needed). You should now see the todo.sqlite file inside of the resource folder.
Now that we have added the database, we need to load the Objective C libraries so we can use it. Do a control-click (right click) on the Frameworks folder. Click Add -> Existing Frameworks. Now this part is a little strange. It has been my experience that these libraries are not in the same place on all machines. So in the search bar type in libsqlite3. The file we are looking for is called libsqlite3.0.dylib. This may pull up multiple files as OSX has it’s own versions of this file. Just click on the largest of the files that show up and click Add. As you can see, mine is about 1.7 MB.
Now it should add the framework and your directory will look something like this:
We need to create an object to hold our todo information. We will eventually be making an array of these objects to populate a UITableView. Go ahead and click File -> New File… Select NSObject Subclass and click Next.
Name this object todo.m and check the box that says Also create “Todo.h” and click Finish.
Open up todo.h and add the following code.
We see some new things here…First, there is a variable of type sqlite3 called database. This will be a reference to the applications database and will allow the todo object to communicate with it. Make sure you add a #import<sqlite3.h> in your imports.
Next, we see a primary key. Notice that in the property declaration it has the keywords assign and readonly. This tells the compiler that this variable, once assiged, can not be changed again. This is good since each todo will be uniquely identified by this variable.
Also, I have declared a method called initWithPrimaryKey. This will be the contstructor for this object. It takes an integer to assign as the primary key and an sqlite3 object to use as the database reference.
Let’s implement this method…Open up todo.m and add the following code.
There are quite a few new things that need to be explained here. I will just go through it line by line.
static sqlite3_stmt *init_statement = nil
This will hold our initialize statement when retrieving todo data from the database. This statement is static, meaning it is independent of any instance. In other words, there will be only one of them no matter how many todo objects we create. This statement will get compiled and allow us to do some neat things. I’ll explain more in a bit.
The next lines makes sure that the super class (NSObject) initilizes properly before we initilize a todo object. We then set the local primary key and database objects to the parameters passed to the initWithPrimaryKey method.
Now some interesting stuff happens. The next lines checks if our init_statment is null. This will happen only once per launch of the application. If it is null, we create a new string containing an SQL statement. If you are familiar with SQL at all, this should look pretty familiar with one exception. What is a question mark doing in there? Well, I will tell you. After the SQL statement gets compiled, we can bind a value to it that will eventually replace the question mark. So this allows us to have 1 generic SQL statement, but bind different values to it to retrieve different results. So the next line, you guessed it, prepares the statement and stores it in our init_statement. The if statement just checks to see if this finished correctly and prints an error if there was a problem.
Moving on… The line sqlite3_bind_int simply replaces that question mark with the primary key of the current todo object, so what we end up with is statements like this:
SELECT text FROM todo WHERE pk = 1;
SELECT text FROM todo WHERE pk = 2;
SELECT text FROM todo WHERE pk = 3;
SELECT text FROM todo WHERE pk = n;
After that, the sqlite3_step(init_statement) method is called. This method executes the SQL statement on the database. It is contained inside of an if statement to make sure it executed properly. Now we can finally access the todo data. We see this line:
self.text = [NSString stringWithUTF8String:(char*) sqlite3_column_text(init_statement,0)];
Wow, that’s a mouthful… Let’s analyze it. The sqlite3_column_text method tells SQL that we want to retrieve a string object from the database. It has 2 parameters. The first, is just a reference to the SQL statement that was used. The second is the column number that we wish to get text from. So in this case, we only have one column (SELECT text FROM…) so there is only 1 index and that’s the 0th index. Next, the (char *) is just a cast to a string (might not be needed, but good practice). And finally, we build an NSString object with the data returned so that we can assign self.text to it.
This is quite a bit to explain in just text. If I have lost you, feel free to ask me questions in the comments.
We are done with the todo object for now…
Go ahead and open up todoAppDelegate.h and add the following code.
This should look a little familiar with the exception of a few lines. Notice that I have created an NSMutableArray of todo objects. This will be (like the fruit example) an array to hold our todo items. We will eventually use this array to populate a UITableView. The only new lines here are the import of sqlite3.h and the sqlite3 *database line. Now let’s open up todoAppDelegate.m and add some code.
One new thing we see here is a private interface. We declared it here because it’s specific to this object so it does not need to be declared in the .h file. The 2 functions we will implement are createEditableCopyOfDatabaseIfNeeded and initializeDatabase. Much of the code for these has already been written for us inside of Apple’s SQLBooks tutorial. I will going through this code and explaining it the best that I can. Add the following code.
What this method is essentially doing is copying the database from your project folder to the documents folder on your iPhone. This will only happen once as it first checks if the database already exists in the documents folder. I’m not going to go through this line by line as it is fairly self explanitory. Apple does a great job of naming functions and variables so that we can understand what is going on. If I get enough requests in the comments, I’ll do a line-by-line writup of this function.
The next function we will implement is initializeDatabase. Add the following code:
That’s a lot of text! Don’t worry it’s mostly comments. Let’s analyze this code…Some of it is very similar to the fruits example.
The first line creates and initializes a NSMutableArray. We then go on to set this array to our object’s todos array and release the temporary object.
The next 3 lines locate the database we created inside of the documents folder. Following that, the sqlite3_open line open’s the database so we can access its data. If the database opens correctly, we then proceed to retrieve todo items. The first line:
const char *sql = "SELECT pk FROM todo";
is an SQL statement that we will use to get all of the primary keys from the database. We then prepare the statement (as we did inside the todo.m file) only this time there is no “?” in the statement. That is because there is not condition for retrieving the primary keys. We are simply saying “give me all of the primary keys in the database”.
Now we see a while loop that is stepping through the SQL results. Every time we call sqlite3_step, the next result gets retrieved. The line:
int primaryKey = sqlite3_column_int(statement,0);
retrieves the primary key from each result. This is very similar to retrieving the text in the todo.m class only we use the sqlite3_column_int method instead of the sqlite3_column_text method. This is done for obvious reasons.
After we have the primary key, we create a new Todo object and call the initWithPrimaryKey constructor that we created. The primary key gets passed as well as a reference to the database. This allows the Todo object to essentially “look itself up” in the database. Finally, we add the newly created Todo object to our array of todos.
The last statement sqlite3_finalize clears the statement from memory and does some other cleanup.
The last part of this tutorial is calling these functions to create and initialize the database. So add the following code to applicationDidFinishLaunching:
We are simply calling these functions. You can now click Build and Go but your application won’t display anything! You might be quite frustrated that you completed this portion of the tutorial and have yet to see anything. Well, stay tuned! I will have the next portion of this tutorial up soon.
For you ambitious programmers you could move on. If you notice, at this point we are in a similar situation as the fruit tutorial. We have an Array of objects that will eventually populate a UITableView.
This tutorial will be a 4 part series and I will show you how to use a few more controls. We will be adding, editing, and deleting todo items. If you have any questions, please leave them in the comments. Also, if you get lost you can download the sample code here
Happy iCoding!
- Posted on 19 Aug 2008 in SQLite, iPhone Programming Tutorials
- Digg |
- Del.icio.us |
- Stumble |
- 94 Comments »
iPhone Programming Tutorial - Populating UITableView With An NSArray
The goal of this tutorial is to show you how to populate a UITableView with data from an array of objects. This will be the building block to display XML data as well as SQL data.
The theme of this application will be fruit. We will create an array of “fruit” objects that have some additional information besides the name. We will populate a UITableView with the names of the fruits. When the user selects a fruit from the list, the view will transition to another one and display specific details about that fruit.
I will try to be as detailed as possible however it would be useful if you have completed the following tutorials as I will use concepts from each of them:
- Create a Navigation-Based Application
- Create a New Fruit Class Object
- Create and Populate an NSArray
- Add a New View To Your Project
- Connect The View To Code
- Populate A UITableView With Object Data
- Transition To New Views And Show Data Based On The Row Selected
We are going to create our “fruit” objects that will be used in the application. If you are not too familiar with object oriented programming…Google it. That tutorial would be a little too huge for me to write.
Click on File -> New File… The object we are creating will inherit from NSObject, so select NSObject Subclass and click Next.
The next screen will ask you to name it. Go ahead and name it “Fruit” and make sure that “Also create Fruit.h” is checked. It should look like the screen below. Then, click Finish.
Now, we are going to define the properties of a “Fruit” object. For this application a fruit will have a name and a description. Open Fruit.h and add the following code:
We have created the properties needed to represent our fruit. There is one line that you may be unfamiliar with. The line -(id)initWithName:(NSString*)n description:(NSString *)desc; is a definition for a function. This function will be called to initialize a Fruit object. All NSObjects have an init method, but we want to create our own so that we can pass in a name and description when the object is created.
Open up Fruit.m and add the following code:
Here we implement the initWithName method. The code here seems pretty straight forward. We are basically setting our local copies of name and description to the arguments passed to this method. The important thing to notice here is the return self line. This is crucial for using this method as a constructor. It allows this function to return the newly created instance of a fruit object.
Next, we are going to create an array of fruit objects. Open up FruitAppDelegate.h and add the following code:
All we are really adding here is an NSMutableArray property. I used NSMutableArray instead of NSArray because it has a few more methods making it more flexible.
Now, open up FruitAppDelegate.m and add @synthesize fruits to the top. This is so other objects will have access to the fruits array. Also, be sure to include the import statement for Fruit.h.
Now add the following code to the applicationDidFinishLaunching method.
What we are doing here in the 1st three lines is creating new instances of a fruit object. Notice that instead of calling init, we are calling the initWithName method that we created. This is allowing us to pass in a name and a description to each of the fruits.
The next line [self.fruits = [[NSMutableArray alloc] initWithObjects:apple,orange,watermelon,nil]; builds a new array from the objects we just created. It is important to pass in nil as the last argument in an NSMutableArray. It will not work unless you remember this.
Now we are going to create the view that will be displayed when the user selects a fruit. Double click on any one of your .xib files to open up Interface Builder.
Click File -> New and select view and click choose.
You should now see the new view (it will be blank) and the objects associated with it. We need some sort of text field to display the description of the fruit. For this tutorial I have chosen a UITextView as opposed to a UITextField. This is because a UITextView is multi-line and is great for displaying more than one line of text. So, go ahead and drag it on to your view. Your view window should now look like this:
Now click File -> Save. One important thing to keep in mind is to make sure you are saving it in the current project’s directory. It seems that every time I add a view to a project, the default directory is not my project’s directory. Name this file FruitViewController and click Save.
Another window should show up after you click save. It is asking you if you want to add this view to your project. Just check the box net to Fruit ,click Add, and close Interface Builder.
Close Interface Builder and go back to X-Code.
We need to create a ViewController to handle our View. Click File -> New File… Select UIViewController subclass and click Next.
Name this file FruitViewController.m and check the box that says “Also create “FruitViewController.h” . Click Finish.
Now we will declare an Interface Builder Outlet for the UITextView that we added to the view. Open up FruitViewController.h and add the following code.
This line allows us to associate the fruitDescription property with the UITextView we created. Open up FruitViewController.m and add this code underneath @implementation keyword. This creates default “getter” and “setter” methods for the fruitDescription property.
Double click on FruitViewController.xib to open it in interface builder. We need to connect the view to the FruitViewController class we just created. Click on the File’s Owner object.
Click Tools -> Identity Inspector. Select FruitViewController from the dropdown next to class. Notice that under the Class Outlets section you will see the UITextView property we created.
The last step in interface builder is to connect the UITextView. Click Tools -> Connection Inspector. You should see an Outlet that says fruitDescription. Click in the corresponding circle and drag it over the UITextView on your view and release it.
Now, click the circle next the word View under outlets and drag it to the View object inside of the window that says FruitViewController in the title. When you are done the screen should look like this:
Now close Interface Builder.
The first thing we are going to do here is create a property for our new view so that it can be transitioned to when a fruit gets clicked on. Open RootViewController.h and add the following code:
We are just creating a property for the fruitViewController that we added to the project. Also note that I added the #import “FruitViewController.h” line. this will allow us to create new instances of the FruitViewController object.
Now open the RootViewController.m and find the numberOfRowsInSection method. This method tells the UITableView how many rows it will be displaying. In our case it will be the size of the array of fruits. Add the following code (click the image to enlarge):
The first line allows us to gain access to the appDelegate of our application. This is where we defined the fruit array. Once we have access to the delegate the count property of the fruit gets returned.
Now find the cellForRowAtIndexPath method and add the following code:
So the first line we added is the “FruitAppDelegate *appDelegate…” line. Again, this is giving us access to the appDelegate object where we declared the fruit array. The next line calls the objectAtIndex method on the Array of fruits. The index we will be using can be accessed via indexPath.row. This is an integer value representing each row of the UITableView. Finally, we call the setText method of the cell, to display the name of the fruit in each cell at the given index.
This is the last step. We are going to detect which row in the UITableView the user selected. Find the method called didSelectRow and add the following code(click image to enlarge).
This method gets called every time a user taps on a cell in the UITableView. The parameter indexPath has a property called row that is the integer value of the cell the user clicked on. To access this, we call indexPath.row.
The first line again gives us access to the appDelegate. The next line indexes into the fruits array and makes a copy of the selected fruit object.
The next section starting with “if(self.fruitView == nil)”, initializes the viewController if it hasn’t already been initialized (see my previous tutorial if you need more of an explanation on this). One thing to take note of: Make sure that the parameter you pass to initWithNibName matches the name of the .xib file you used for your view. So in our case, its FruitViewController.
Following this line is the line that pushes the viewController on to the navigationController stack. This causes the view to transition to the new view.
The last 2 lines pass the fruit information to the new view. They are fairly self explanitory. We first set the title of the view to the name of the fruit and then set the description text to the description of the fruit.
Now click Build and Go and your app should launch. Here are some screenshots of how it should look.
And after clicking on a fruit…
Well, I hope that you got a lot out of this tutorial. As always, if you have any questions or comments, feel free to leave them in the comments section of this post. We also have a forum to help you will all of you iphone related questions. If you get lost, you can download the sample code here
Happy iCoding!
- Posted on 8 Aug 2008 in Interface Builder, iPhone Programming Tutorials
- Digg |
- Del.icio.us |
- Stumble |
- 142 Comments »
The I’s have it! iCodeBlog Now Has A Forum (for now)
OK, so 20-someodd votes for a forum has swayed me for now. I went ahead and put up a forum on iCodeBlog. This will be experimental as it’s such a sad site to see failing forums with a lack of participation. With that in mind, I will set a goal:
If the forum has at least 50 registered users by next week 08/14/08 (which shouldn’t be that hard, the site already gets over 500 unique visits per day), it stays. If not, I will take it down. A forum takes a lot of work to maintain and attract new users. I am willing to put in that effort, if there is enough interest.
So go fourth and register for the forums.
Happy iCoding!
- Posted on 7 Aug 2008 in iPhone Articles
- Digg |
- Del.icio.us |
- Stumble |
- 3 Comments »
Forums on iCodeBlog
There have been some recent talks about putting some sort of forum/discussion system on iCodeBlog. It appears that writing problems and solutions in the comments section is not sufficient. I’m not too sure about this as I feel this might make the site a little cluttered. However, I am completely willing to put one in place if enough people are interested and could find benefit in it.
With that in mind, I have created a poll. Go ahead and fill it out and if enough people want a forum, I will put one on iCodeBlog.
[poll id=2]
Let me know what you guys think…
Happy iCoding!
- Posted on 6 Aug 2008 in iPhone Articles
- Digg |
- Del.icio.us |
- Stumble |
- 8 Comments »
iPhone 2.0.1 Firmware Update
Well, it has been about 3 weeks now since the launch of the iPhone and Apple has released the much anticipated 2.0.1 software update for the iPhone yesterday.
Since downloading this 250 MB beast of firmware, I haven’t had much time to play with it. After a quick runthrough of a few programs, I have noticed an overall performance improvement. They seemed to have fixed the lag when scrolling through contacts, which was a huge frustration for me.
I can’t give a full review on it yet as it is too early on, but I would really like to know what you guys think about the update. Have you noticed any significant improvement? Leave me a note in the comments.
Stay tuned for another tutorial a little later this week. I will be showing you how to populate a UITableView from an array of objects.
Happy iCoding!
- Posted on 5 Aug 2008 in iPhone Articles
- Digg |
- Del.icio.us |
- Stumble |
- 5 Comments »












































