I cannot get the staffs from the SQLIte DB to iOS table view
I am stuck in iOS application that works on SQLite. I have created a Coffee table with different types of coffee names and prices along with the coffee ID which acts as the primary key. In SQLite I could run the SQL queries and got the correct answers. But while getting the coffee names in iOS table view, I got nothing except the blank table and section title. While debugging the code I found that while(sqlite3_step(selectstmt) == SQLITE_ROW) is not working as sqlite3_step(selectstmt) returns 101 value (i.e. SQLITE_DONE) instead of SQLITE_ROW (i.e value 100) even if I tried with sqlite3_reset() before executing sqlite3_step(). I could not figure out how to solve it.
Here is my code of coffee.m
#import "Coffee.h"
#import "SQLAppDelegate.h"
static sqlite3 *database = nil;
static sqlite3_stmt *deleteStmt = nil;
static sqlite3_stmt *addStmt = nil;
@implementation Coffee
@synthesize coffeeID, coffeeName, price, isDirty, isDetailViewHydrated;
- (void) dealloc {
[price release];
[coffeeName release];
[super dealloc];
}
+ (void) getInitialDataToDisplay:(NSString *)dbPath{
SQLAppDelegate *appDelegate = (SQLAppDelegate *)[[UIApplication sharedApplication] delegate];
if(sqlite3_open([dbPath UTF8String], &database)==SQLITE_OK){
const char *sql = "select CoffeeID, CoffeeName from Coffee";
sqlite3_stmt *selectstmt = nil;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL)== SQLITE_OK){
sqlite3_reset(selectstmt);
//NSLog(@"Macro %d",sqlite3_step(selectstmt));
while(sqlite3_step(selectstmt) == SQLITE_ROW){
NSInteger primaryKey = sqlite3_column_int(selectstmt,0);
NSLog(@"The P key is %d:",primaryKey);
Coffee *coffeeObj = [[Coffee alloc] initWithPrimaryKey:primaryKey];
coffeeObj.coffeeName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
coffeeObj.isDirty = NO;
[appDelegate.coffeeArray addObject:coffeeObj];
[coffeeObj release];
}
}
}
else
sqlite3_close(database);
}
- (id) initWithPrimaryKey:(NSInteger ) pk{
[super init];
coffeeID = pk;
NSLog(@"%d",coffeeID);
isDetailViewHydrated = NO;
return self;
}
+ (void)finalizeStatements {
if(database)
sqlite3_close(database);
}
@end
+++++++++++++ RootViewController.m +++++++++++++
\#import "RootViewController.h"
\#import "Coffee.h"
@implementation RootViewController
\#pragma mark -
\#pragma mark View lifecycle
\- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
appDelegate = (SQLAppDelegate *)[[UIApplication sharedApplication]delegate];
self.title = @"Name List";//Coffee List;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
\#pragma mark -
\#pragma mark Table view data source
// Customize the number of sections in the table view.
\- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
\- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(@"Rows %d",[appDelegate.coffeeArray count]);
return [appDelegate.coffeeArray count];
}
// Customize the appearance of table view cells.
\- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell 开发者_JAVA百科= [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
Coffee *coffeeObj = [appDelegate.coffeeArray objectAtIndex:indexPath.row];
cell.textLabel.text = coffeeObj.coffeeName;
return cell;
}
+++++++++++++ SQLAppDelegate.m +++++++++++++
\#import "SQLAppDelegate.h"
\#import "RootViewController.h"
\#import "Coffee.h"
@implementation SQLAppDelegate
@synthesize window;
@synthesize navigationController;
@synthesize coffeeArray;
\#pragma mark -
\#pragma mark Application lifecycle
\- (void) copyDatabaseIfNeeded {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath = [self getDBPath];
// NSLog(@"%@",dbPath);
BOOL success = [fileManager fileExistsAtPath:dbPath];
NSLog(@"%d",success);
if(!success){
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"CoffeeDetail.sqlite"];
success =[fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if(!success)
NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
}
}
\- (NSString *)getDBPath{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir = [paths objectAtIndex:0];
//NSLog(@"dbpath %@",[documentDir stringByAppendingPathComponent:@"SQL.sqlite"]);
return [documentDir stringByAppendingPathComponent:@"CoffeeDetail.sqlite"];
}
\- (void) removeCoffee:(Coffee *)coffeeObj{
//Delete from DataBase
[coffeeObj deleteCoffee];
//Delete from the array
[coffeeArray removeObject:coffeeObj];
}
\- (void)applicationDidFinishLaunching:(UIApplication *)application {
[self copyDatabaseIfNeeded];
NSMutableArray *tempArray =[[NSMutableArray alloc]init];
self.coffeeArray = tempArray;
[tempArray release];
[Coffee getInitialDataToDisplay:[self getDBPath]];
NSLog(@"Array =%@", self.coffeeArray);
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
}
\- (void) deleteCoffee{
if(deleteStmt == nil){
const char *sql = "delete from Coffee where coffeeID = ?";
if(sqlite3_prepare_v2(database, sql, -1, &deleteStmt, NULL) != SQLITE_OK)
NSAssert1(0,@"Error while creating the delete Statement. '%s'", sqlite3_errmsg(database));
}
sqlite3_bind_int(deleteStmt, 1, coffeeID);
if(SQLITE_DONE != sqlite3_step(deleteStmt))
NSAssert1(0,@"Error while deleting. '%s'", sqlite3_errmsg(database));
sqlite3_reset(deleteStmt);
}
I think in deleteCoffee
you're trying to use a variable that isn't set (database
).
In my sqlite apps I have this method:
-(sqlite3 *) getNewDBConnection{
sqlite3 *newDBconnection;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"data.sqlite"];
// Open the database. The database was prepared outside the application.
if (sqlite3_open([path UTF8String], &newDBconnection) == SQLITE_OK) {
//NSLog(@"Database Successfully Opened");
} else {
NSLog(@"Error in opening database");
}
return newDBconnection;
}
and then in the methods that access the DB, I have something like:
- (void) deleteCoffee{
sqlite3 *database = [self getNewDBConnection]; //see this line
if(deleteStmt == nil){
const char *sql = "delete from Coffee where coffeeID = ?";
if(sqlite3_prepare_v2(database, sql, -1, &deleteStmt, NULL) != SQLITE_OK)
NSLog(@"Error while creating the delete Statement. '%s'", sqlite3_errmsg(database));
}
sqlite3_bind_int(deleteStmt, 1, coffeeID);
if(SQLITE_DONE != sqlite3_step(deleteStmt))
NSLog(@"Error while deleting. '%s'", sqlite3_errmsg(database));
sqlite3_reset(deleteStmt);
}
精彩评论