How To Develop an iPhone or iPad App using SQLite Data and an UITableView | iOS 5 | Tutorial
By klanguedoc
iOS 5 makes displaying in a UITableView quick and easier with a lot less code than previous versions of the SDK. On the back side, SQLite is a great data persistence facility. Marrying the two together makes for a perfect combination for building IOS 5 apps.
This tutorial will demonstrate how to read data from a SQLite database, store that data in a NSMutableArray and display it in a UITableView.
Create a SQLite Database
For the sake of this tutorial, create a database with Firefox SQLite Manager addin. I am calling mine authorsDb.sqlite. I am going save it to a convenient location because I will need to copy it into the Xcode project through Xcode and Finder.
The database will have one table, books, with the following columns:
I add the following data to the table via the SQLite Firefox addin:
Once this task is complete, I will create the project and add the database.
Create a IOS Project
The first step is to create a Single View project that targets the iPhone. Make sure the storyboard option is enabled. Once the project is created and loaded delete the View Controller and in its place create a UITableViewController by dragging it onto the Storyboard canvas.
Select the Cell prototype and give it an unique Identifier in the Attributes Inspector
Expand the Frameworks folder and select the first framework. Right click on it and select “Show in Finder”. When Finders opens move up the enclosing folder until to get to the “usr” folder
Expand the "usr" folder and expand the lib folder. Scroll down to the, libsqlite3.0.dylib, library alias. Using the left mouse button, drag the alias to the root of the Frameworks folder. A Copy Page will display, make sure to uncheck the “Copy items into destination...” otherwise the alias will be copied into the Frameworks folder and will break your SQLite installation. By unchecking this option, while leaving the other checked, you are adding a reference only.
Next right click on the file in the FirstTableProject folder and select “Show in Finder”, navigate to the location where the authorsDb.sqlite file was saved. Repeat the same operation as before, but this time leave the copy option checked because we need to have Xcode copy the database file into the project.
Now that the database is setup, I am going to create a UITableViewController in the next step.
Create the AuthorVC UITableViewController
Create the AuthorVC UITableViewController by selecting Add new File in the menu. Select the UIViewController under the Cocoa Touch node. On the next page enter the AuthorVC name and change the subclass to UITableViewController
Make sure the iPad option is not selected.
Once the authorVC class is created, open the Storyboard and select the UITableView and add the class to he Custom Class field in the Attributes Inspector.
Next repeat the same operation in the following task. We will come back to this class in a moment in regards to creating a Objective-C class only.
Create Author Class
To create the Author class, repeat the same steps as before but choose the Objective-C class template instead. On the second page, enter the Author class name, the sub class must be NSObject
Add three instance variables like the screenshot below:
and implement them in the implementation file author.m
Implement AuthorVC
The step is the heart of the tutorial, adding data to the UITableView. Open the header file and import the sqlite3.h header file and declare a sqlite3 variable. Also declare a NSMutableArray instance variable.
Create a method, authorList with a NSMutableArray return type
Save the file and open the AuthorVC implementation file.
The first thing to do in the implementation file is add the sqlite3 library and author.h libs in the import section and implement the “theauthors” NSMutableArray using the @synthesize directive.
Two required UITableView methods must be imlemented are
- numberOfSectionsInTableView
- numberOfRowsInSection
The first one defines the number of sections and the second defines the number of rows per section. This is usually the count of the Array that is being used to populate the UITableView.
Next, implement the dataList NSMutableArray:
The method first defines the “theauthors” NSMutableArray. Next a NSFileManager object is defined, followed by a NSString instance variable for the db path. The code continues by checking to make sure the database file is indeed in the Resource path and attempts to open it. If all goes well, a query string of char is define and initialized with the query string.
Next a sqlite3_statement is defined and finally the sqlite3_prepare is called, passing in all the variables. If the statement is ok and successfully executed, an Author object is created and initialized. The next step will populate the “theauthors” NSMutableArray using a while expression to step through the rows with command sqlite3_step and adding the row data to the author properties. Make sure to add the author object to the array at the end otherwise the table will be empty.
Configure UITableViewCell
A couple of steps to complete this tutorial. Configure the UITableViewCell with the method, cellForRowAtIndexPath. First change the value of the “CellIdentifier” to the name you gave the Cell prototype.
Next define an int variable for the rowIndex which will be used to extract the corresponding value from the “theauthors” NSMutableArray. Define a new Author object and assign the author object at the rowIndex in the NSMutableArray.
Complete the method by adding the values to the cell.textLabel and cell.textDescription properties. That’s it.
ViewDidLoad
One final step is to call the dataList NSMutableArray method when the UITableViewController loads in the viewDidLoad method:
In Summary
UITableView offers some very powerful features to organize and display, which were out of the scope of this tutorial. SQLite and UITableView are both easy to work with for storing data and displaying it.
For more tutorials on SQLite programming with iOS for iPad or iPhone Apps check out the tutorials:
How to Add CRUD (Insert, Update, Delete) to iPad or iPhone Apps
|
|
5-in-1 Camera Connection Kit USB AV Video Cable Accessories For iPad 1 2 EA511
Current Bid: $19.89
|
|
|
5-in-1 Camera Connection Kit USB AV Video Cable Accessories For iPad 1 2 EA511
Current Bid: $16.98
|
|
|
5-in-1 Camera Connection Kit USB AV Video Cable Accessories For iPad/iPad2
Current Bid: $19.65
|
|
|
5-in-1 Camera Connection Kit USB AV Video Cable Accessories For iPad 1 2 EA511
Current Bid: $25.95
|
|
|
5-in-1 Camera Connection Kit USB AV Video Cable Accessories For iPad 1 2 EA511
Current Bid: $25.99
|
Author.h
//
// Author.h
// FirstTableProject
//
// Created by Kevin Languedoc on 12/5/11.
// Copyright (c) 2011 kCodebook. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Author : NSObject{
NSString *name;
NSString *title;
NSString *genre;
}
@property(nonatomic,copy) NSString *name;
@property(nonatomic,copy) NSString *title;
@property(nonatomic,copy) NSString *genre;
@end
Author.m
// // Author.m // FirstTableProject // // Created by Kevin Languedoc on 12/5/11. // Copyright (c) 2011 kCodebook. All rights reserved. // #import "Author.h" @implementation Author @synthesize name; @synthesize title; @synthesize genre; @end
AuthorVC.h
//
// AuthorVC.h
// FirstTableProject
//
// Created by Kevin Languedoc on 12/5/11.
// Copyright (c) 2011 kCodebook. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <sqlite3.h>
@interface AuthorVC : UITableViewController{
NSMutableArray *theauthors;
sqlite3 * db;
}
@property(nonatomic,retain) NSMutableArray *theauthors;
-(NSMutableArray *) authorList;
@end
AuthorVC.m
//
// AuthorVC.m
// FirstTableProject
//
// Created by Kevin Languedoc on 12/5/11.
// Copyright (c) 2011 kCodebook. All rights reserved.
//
#import "AuthorVC.h"
#import "Author.h"
#import <sqlite3.h>
@implementation AuthorVC
@synthesize theauthors;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[self authorList];
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.theauthors count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"AuthorsCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
int rowCount = indexPath.row;
Author *author = [self.theauthors objectAtIndex:rowCount];
cell.textLabel.text = author.name;
cell.detailTextLabel.text = author.title;
return cell;
}
-(NSMutableArray *) authorList{
theauthors = [[NSMutableArray alloc] initWithCapacity:10];
@try {
NSFileManager *fileMgr = [NSFileManager defaultManager];
NSString *dbPath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:@"AuthorsDb.sqlite"];
BOOL success = [fileMgr fileExistsAtPath:dbPath];
if(!success)
{
NSLog(@"Cannot locate database file '%@'.", dbPath);
}
if(!(sqlite3_open([dbPath UTF8String], &db) == SQLITE_OK))
{
NSLog(@"An error has occured: %@", sqlite3_errmsg(db));
}
const char *sql = "SELECT * FROM books";
sqlite3_stmt *sqlStatement;
if(sqlite3_prepare(db, sql, -1, &sqlStatement, NULL) != SQLITE_OK)
{
NSLog(@"Problem with prepare statement: %@", sqlite3_errmsg(db));
}else{
while (sqlite3_step(sqlStatement)==SQLITE_ROW) {
Author * author = [[Author alloc] init];
author.name = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,1)];
author.title = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,2)];
author.genre = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 3)];
[theauthors addObject:author];
}
}
}
@catch (NSException *exception) {
NSLog(@"Problem with prepare statement: %@", sqlite3_errmsg(db));
}
@finally {
sqlite3_finalize(sqlStatement);
sqlite3_close(db);
return theauthors;
}
}
@end
Comments
Hi BareFeetTom, thanks for your comment.
I totally agree with you with what you are saying. The objective of the tutorial was to demonstrate to another developer how to load data from SQLite into an UITableView. The tutorial was in response to his request, so I obliged. Your tutorial is good.
One area of using plain sqlite instead of core data intrigues me, as I am finding it quite difficult to search across core data entities. Where as, using sqlite, I can write code to achieve searches across tables without too much bother.
Comments?
True, using good old SQL is fast and easy. I am a big fan but I also believe in the whole ORM ideology, which is what Core Data really is. I have used ORM technology on other platforms like Linq (.Net) and Hibernate (Java). So far both Linq and Core Data have an edge over Hibernate.
As for SQL, there will always be a place for both. You just got to know when you use which.
Thanks for doing this tutorial!! It's give me a better idea on how to implement the DB. I've followed through it all, but I seem to be getting one error for this line in the AuthoVC.m:
sqlite3_finalize(sqlStatement);
I get the error:
Use of undeclared indetifier 'sqlStatement', the above lines which reference it are fine though. Any ideas what might be wrong?
When I comment the line out I can build the project, but it only shows the last record in my DB table and it's shown three times.
Hope you can help.
Move the code up to :
....
}
sqlite3_finalize(sqlStatement);
}
@catch (NSException *exception) {
NSLog(@"Problem with prepare statement
This is my mistake. Sorry for throwing a curve...
Yep that's better now, but I still only get the last row shown in my table and it shows three times, have I done something wrong?
Any idea on why it won't let me set the UITableView to the custom class of my VC?
Thanks
Never mind about connecting the VC. I am now having the same problem as Mark.
Check your array elements (index) at the start of the method, does your array list the proper items, or does the array list all three last items?
This part of the code, I believe, is the problem:
Author * author = [[Author alloc] init];
while (sqlite3_step(sqlStatement)==SQLITE_ROW) {
author.name = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,1)];
author.title = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,2)];
author.genre = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 3)];
[theauthors addObject:author];
}
Every time an item is added to the array it overrides the others. Before the item is added I do an nslog to make sure that the object added is different (which it is), but if I do an nslog immediately after that while statement, I find all of the items in the array are now exactly the same.
I found the problem:
Author * author = [[Author alloc] init];
should be inside of that while loop. Put it inside and everything works fine
Will,
Move:
Author * author = [[Author alloc] init];
into the while loop.
Thanks for posting it helped me see it :)
Team work!
Great team work. Sorry I wasn't there to help. I had a dinner party. I am glad you figured it out.
I have updated the source code in the tutorial. Thanks.
Thanks again for doing the tutorial Kevin. I was looking at being able to create a detail view for when a row is selected. I've created a view controller for the view and called the identifier 'detail'.
I've tried to add the following in the authorvc.h under:didSelectRowAtIndexPath
DetailViewController *detail =[self.storyboard instantiateViewControllerWithIdentifier:@"detail"];
[self.navigationController pushViewController:detail animated:YES];
But when I click on a row in the simulator nothing happens, I've also tried creating a segue from the table to the detail view but still nothing. Do you have any ideas why the detail view isn't being pushed on? Thanks.
Glad to see your app is moving along. To use instantiateViewControllerWithIdentifier, add after your code:
detail.TextViewObject= [self.ArrayObject objectAtIndex:index];
[self.navigationController pushViewController:detail animated:YES];
For segues, use something like:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"nameOfSegue"]) {
[[segue destinationViewController] setDelegate:self];
}
}
Hope this helps. This is not tested and may require more tweaking.
Kevin
Nice tutorial Sir,
But I am facing one problem.
It is giving the last entry in my database as output. I rechecked the code but again the same thing.
Please Help..
Thanks.
Please read the comment above. You need to move the Author * author = [[Author alloc] init]; into the loop. Please review my corrected source code. Hope this helps.
I can't display the detailTextLabel.text part on the table view. I have followed this exactly. Here is the code portion:
Korean *korean = [self.vocab objectAtIndex:rowCount];
cell.textLabel.text = korean.Korean;
cell.detailTextLabel.text = korean.Romanization;
cell.detailTextLabel.text = korean.English;
Am I missing something? Even when I remove one of those, I still get nothing.
You code looks fine. Are you getting sn error message? Is your cellIdentifier properly set? The string value must match exactly the one set in the cell prototype in the storyboard.
No error message, just not displaying the Romanization and English on the same line as the characters. I've set the cell identifier as VocabCell and declared the same in the UITableViewController. (I'm also doing this an a iPad app if that helps any).
Mike, this is kind of hard to analyze without seeing your code, and i am not asking to post anything here, have you looked at table config; how many sections are configure and your groupings. Are these set to display all your data? Instead of loading your data form the db, have you tried just display static text in each of the fields in the cell?
Sorry if this sounds like a stupid question (as i'm only starting out in programming).
I've learnt a lot from your code, but when i try using a table where one of the fields/columns is mostly made of integers (postcodes), i can't seem get it to work.
i've declared the variable as an integer and a postcode and tried various ways of relabelling the field as a varchar but to no avail.
Any ideas how i could do this?
For example i can use
bar.Suburb = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,2)];
but not
NSInteger PostCode = sqlite3_column_int(sqlStatement, 3)
or
bar.PostCode = NSINTEGER_DEFINED (integerValue) sqlite3_column_int(sqlStatement, 3)
i tried another column with fresh numbers and worked out that the database that i'm working with had some data that was incompatible. I went through thousands of records and took out any special characters and filled out any null cells with a default values. I think i can figure out how to convert the string to integer with no real hassle, although i'm struggling with how i can leave in special characters (its gotta be there somewhere). Any help would be great
No question is stupid! This is one of the confusing areas of Objective-C; int and NSInteger are essentially two different data types. It's like saying NSInteger is int on steriods. NSInteger is 32/64 bits and int is 16 bits, so you try something like this:
int one = 5;
NSNumber * anotherone;
anotherone = [NSNumber numberWithInt:one];
NSLog(@"value of one: %@", anotherone);
I should clarify, NSInteger is a wrapper class of type long.
Hello, I'm trying to figure out how to make queries on my code, like you made "select * from books" but when I try select name from books for example it gives me GDB, any idea?
Thanks!
Hi Renan Can you see an error message in the Console. This would help a lot in deciphering the issue. Of the top of my head, nothing comes to mind, except is your db object properly set and does the db open?
Yes, actually I didn't get any error, just GDB, nothing above it... Just copy your entire code and substitute this part SELECT * FROM books --- for this SELECT id FROM books
for example, if you have id on your table, I guess you'll have...and that's it, GDB
id may refer to the data type id in Objective-C. In a real app, the primary key column should be named something other than id. Try the other columns.
Sorry, sort of going off topic, I've been looking at using the master-detail app template for ipad which Apple supply, but I want to have multiple detail views. I've tried to find some tutorials which use this with storyboard, but I cant find much.
Do you know of any good tutorials which go through how to do this? Maybe could you look at doing something like this for a future tutorial or your book?
You would need to implement some logic in the tableView method that loads the data into the TableView, Either a switch or and If op.
or
implement the same logic in the prepareForSegue method which would take your cell title value and based on value would the appropriate segue and also transfer the data to the proper DetailViewController. I will post some code...
Hi Renan,
Try something like this. It is not testing and may require some tweaking...
(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSString * segueName = [[NSString alloc] init];
if(tableViewCell == @"value")
{
segueName = [segue identifier];
}
if ([segue.identifier isEqualToString:segueName ])
{
// Get the detail view controller.
PhraseDetailViewController* destVC =
(PhraseDetailViewController*)segue.destinationViewController;
// Find the correct dictionary from the documents array.
NSIndexPath *cellPath = [self.tableView indexPathForSelectedRow];
UITableViewCell *theCell = [self.tableView cellForRowAtIndexPath:cellPath];
// Assign the URL to the detail view controller and
// set the title of the view controller to the doc name.
destVC.detailItem = theCell.textLabel.text;
destVC.navigationItem.title = theCell.detailTextLabel.text;
else if([segue.identifier isEqualToString:@"AnotherSeqgue Value"])
{
....
}
Nice tutorial... It helped me a lot.
Glad to hear Anil. Thanks for your kinds words
Hi Kevin,
I dropped you a mail, do you mind taking a look when you have a chance please?
Sure, no problem
Hi Mark
I checked my mail. The last e-mail from 02/29/2012 but there is no attachment. Can you resend please.
Thanks
Kevin
Hey Kevin,
I'm still stuck!! Can you see the last mail I sent? Really don't know what might be wrong!
Sorry Mark. I had a tough week. I will check your code.
Thanx for your help, I found a way to do it using what you suggested, I have a monster of a switch variable loop combo that I need to work on now. Cheers
Cool, I am glad I was able to help. It is so frustrating to bang our heads over a piece of code that won't do what we want.
K
good tutorial...
Thanks manojglobal
Hi Kevin,
Great tutorial. I have done it twice and am getting the same error message:
Its EXC_BAD_ACCESS(code=1 address=0x073206f76) and when I run the code it stops at the line NSLog() in the code below in the "-(NSMutableArray *) authorList" method in the "AuthorVC.m" file.
I'm assuming its finding the database, but having a problem with the Select statement? I have doublechecked and the database and table are both named the same as in the tutorial. Any ideas?
const char *sql = "SELECT * FROM books";
sqlite3_stmt *sqlStatement;
if(sqlite3_prepare(db, sql, -1, &sqlStatement, NULL) != SQLITE_OK)
{
NSLog(@"Problem with prepare statement: %@", sqlite3_errmsg(db));
thanks Kevin!
Ric
Thanks for the feedback
Try replacing the "*" with the actual column names. The bad_access_exec usually means that an object is null. Otherwise the code looks fine.
Hi Kevin,
I figured it out, sort of. I just recreated the database and gave it a different name in the dbPath. I guess it was stuck on a different version of the database somewhere.
Anyhooo, great tutorial. thanks, ric
I am glad everything sorted itself out. Happy coding.
I have another question on this. (moved onto the next app), Would it be possible to increase this loading to load 25 to 100 at a time without crashing an app? If so, what would be a better way?
Hi Mikey,
You want to load 25 to 100 from db or into table view. For a select, you could try top 25 or 100 , like select top(100) col from table. There shouldn't be any issues assigning an array to the data source, no matter what size within reason.
OK. I'll try it out and see if there are any issues with that.
Hi, thank you for great tutorial! I have an appeal, I would really appreciate if somebody could spread this tableView tutorial with detailed viewController...for example by tapping on some row it will query to particural detail view with some more info coming from the same sqlite DB...Thank you very much for any advise or illustrative tutorial.
It is a bit different task than developing the app withouth storyboard. Thanks again!!
Sure I will glad to help. Once you know how, it is quite easy.
To Klanguedoc, I'm really happy that you are going to help me :-) I'am quite curious about it! :-)
Thanks a lot!
I am nearly finished the code. i will write up the instructions later today
Hi, thanks for the Great tutorial. Everything works fine.
I have a question: "How can I add an image to the tableview?"
I hope you can give me some code. Thanks...
thanks for the great feedback..
Please see the tutorial at URL below, but add use the cell.imageView.image to assign an UIImage resource to the cell.
Wow! Thank you many times "klanguedoc". I am looking forwar to learn this piece of code :-) later today.
You are very welcome Jakub. i am glad you appreciate
plz let me know how can i get all the values from the array into my another class
thank u...
You could use the count property of the array to loop through the array and assign the values using the objectAtIndex method eventhough this last method is in the NSArray class
note: the comment box doesn't allow less than or greater than signs, so replace the "less than" by the proper symbol.
for(int i=0; i less than nsmutablearray.count; i++)
{
yourClass * val = [[yourClass alloc] init];
val.something = [nsmutablearray objectAtIndex:i];
}
I didn't test this so some tweaking may be necessary.
Kevin
Any chance that you might be interested in doing something like this for core data?
Sure Mike,
I will try to put something together over the weekend if I can move my current chapter along a bit. Actually I really like working with Core Data because I used hibernate on Java and Linq with C# a lot and Linq / C# is very similar to Core Data.
Hi Thanks for your grade tutorial
I have the same error here, I 'm really new and I have everything step by step as your tutorial
Its EXC_BAD_ACCESS(code=1 address=0x073206f76) and when I run the code it stops at the line NSLog() in the code below in the "-(NSMutableArray *) authorList" method in the "AuthorVC.m" file.
I don't know what should I replace here as you said
Try replacing the "*" with the actual column names. The bad_access_exec usually means that an object is null. Otherwise the code looks fine.
since everything for me is the same as your tutorial would you please let me know what should I write :)
Thanks in Advance
I forgot to say, Is it possible for you to put your actual project in your tutorials?
Hi Adam,
Since the source code is already in the tutorial, if you send me an e-mail, I will be to send you the project code. Because there is no way to attach the project itself to this web site.
Hi Thanks for your care and reply, I don't have your email address here is mine
adam.f32f@yahoo.com
would you please send me this project and also How-To Display SQLite Data in a UITableView and DetailViewController project
Thank you so much
UITableViewController error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UITableViewController loadView] loaded the "2-view-16" nib but didn't get a UITableView.'
Problem?
Are you using a storyboard or nib file? did you add elements and IBOutlets or IBactions to the storyboard and then removed them? if so, the storyboard still has a reference in the XML. open the storyboard as source code and search for 2-view-16.
BareFeetTom 3 months ago
Nice tutorial, but I think one major flaw in your approach. The whole idea of the UITableViewController (specifically, being a delegate for answering data requests from the UITableView) is to only load the data that you need to display.
SQLite is very good at retrieving one row at a time as needed, so the cellForRowAtIndexPath method should ask SQLite just for the row of data matching the requested indexPath (and only the needed columns).
By contrast, you are caching the entire SQLite table into an NSMutableArray (theauthors). If your SQLite table contains a thousand or a million rows but the UITableView is only displaying ten at a time, then this is a huge waste of time, memory and will probably crash your app.
You can see another approach here, though the tutorial itself is not as well put together as yours:
http://www.barefeetware.com/sqlite/iosxcode/?li
Tom