我的iPhone应用程序中存在SQLite的大问题,需要尽快为客户修复!基本上我是从数据库中提取一个列并将其加载到viewWillAppear上的表视图中。它工作正常,前几次加载视图但突然它开始返回空(null)值。在检查时,似乎打开数据库可能存在问题,但这是我的第一个SQLite项目,因此很难弄清楚发生了什么。
以下是我用来提取SQL信息的代码:
+ (void) getInitialDataToDisplay:(NSString *)dbPath {
NSLog(@"INCOME CALLED 1");
NavTabAppDelegate *appDelegate = (NavTabAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.incomeArray = [[NSMutableArray alloc] init];
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
NSLog(@"INCOME CALLED 2");
const char *sql = "select IncomeID, IncomeName from Income ORDER BY IncomeName asc";
//const char *sql2 = "select categoryID, Size from coffee";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
NSLog(@"INCOME CALLED 3");
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
NSLog(@"INCOME CALLED 4");
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
Income *incomeObj = [[Income alloc] initWithPrimaryKey:primaryKey];
//This is how I pull info from the database using the above select statement and setting it in the coffeeObj property of Coffee class
incomeObj.incomeName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
//coffeeObj.coffeeSize = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)];
incomeObj.isDirty = NO;
[appDelegate.incomeArray addObject:incomeObj];
[incomeObj release];
NSLog(@"INCOME OBJECTS %@", incomeObj.incomeName);
//NSLog(@"CALLED");
}
}
}
else{
sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory
NSLog(@"INCOME CALLED 5");
}
NSLog(@"INCOME CALLED 6");
}
我在viewWillAppear中调用代码如下:
[Income getInitialDataToDisplay:[appDelegate getDBPath]];
这也是发生错误时控制台的输出:
2011-06-17 12:21:48.307 CashCal[318:707] GET DB PATH CALLED
2011-06-17 12:21:48.310 CashCal[318:707] /var/mobile/Applications/2BD7CA1D-C7AB-4425-B5C1-974C4F4D057C/Documents/SQL.sqlite
2011-06-17 12:21:48.312 CashCal[318:707] INCOME CALLED 1
2011-06-17 12:21:48.314 CashCal[318:707] INCOME CALLED 5
2011-06-17 12:21:48.318 CashCal[318:707] INCOME CALLED 6
看来问题出在第一个if语句打开数据库。我真的需要这方面的帮助
答案 0 :(得分:1)
您应该始终通过调用sqlite3_finalize(your_stmt)来销毁预准备语句。并且你应该总是关闭你的连接,不仅仅是因为sqlite3_open()失败了。
也做这样的事情:
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
//your code here
} else {
//print error
NSLog(@"sql-error: %s", sqlite3_errmsg(database));
}
为了澄清,这里是你的数据库的接口,它应该避免在其全部打开时打开数据库,并使代码更清晰
DBi.h
#import <Foundation/Foundation.h>
#import <sqlite3.h>
@interface DBi : NSObject {
sqlite3* db;
}
- (void)opendDB;
- (void)closeDB;
- (NSArray*)getIcons;
@end
DBi.m
#import "DBi.h"
#import "Income.h"
static DBi *sharedDBi = nil;
@implementation DBi
- (void)dealloc {
sqlite3_close(db);
[super dealloc];
}
+ (DBi*)sharedManager {
if (sharedDBi == nil) {
sharedDBi = [[super allocWithZone:NULL] init];
[sharedDBi opendDB];
}
return sharedDBi;
}
+ (id)allocWithZone:(NSZone *)zone {
return [[self sharedManager] retain];
}
- (void)opendDB {
NSString *dbPath = [[NSBundle mainBundle]pathForResource:@"path_to_db_file"ofType:@"sqlite"];
//open the database
if(!sqlite3_open([dbPath UTF8String], &db) == SQLITE_OK) {
NSLog(@"connection to db failed");
sqlite3_close(db);
}
}
- (void)closeDB {
sqlite3_close(db);
}
- (NSArray*)getIncoms {
NSMutableArray rArray = [[[NSMutableArray alloc] init] autorelease];
const char *sql = "select IncomeID, IncomeName from Income ORDER BY IncomeName asc";
//const char *sql2 = "select categoryID, Size from coffee";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(db, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
Income *incomeObj = [[Income alloc] initWithPrimaryKey:primaryKey];
incomeObj.incomeName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
incomeObj.isDirty = NO;
[rArray addObject:incomeObj];
[incomeObj release];
}
} else {
NSLog(@"sql-error in getIncoms: %s", sqlite3_errmsg(db));
}
sqlite3_finalize(selectstmt);
return rArray;
}
现在你可以做那样的事了。
DBi *dbi = [[DBi alloc] init];
NSArray *incoms = [dbi getIncoms];
[dbi release];
希望,那应该有所帮助
答案 1 :(得分:0)
use this code
sqlite3 *database;
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
////your Code
if(sqlite3_prepare_v2(database, [sqlStatement cStringUsingEncoding:NSUTF8StringEncoding], -1, &compiledStatement, NULL) == SQLITE_OK)
{
NSLog(@"%@",sqlStatement);
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
//your code
}
}
sqlite3_finalize(compiledStatement);
sqlite3_close(database);
}
}
答案 2 :(得分:0)
将FMDB用于sqlite任务。在应用程序中的任何地方使用sqlite调用都是不好的做法。只需在谷歌上搜索FMDB例如你会找到一个。 FMDB比SQLIte更容易实现,因为FMDB处理所有事情。
答案 3 :(得分:0)
事实证明,在语句每次都有机会最终确定之前,我在两个不同的地方快速连续调用相同的SQL方法。我想这会导致某种重叠,最终导致语句失效。谢谢你的帮助。我下次肯定会使用CoreData或FMDB。