SQLite突然在iPhone应用程序中没有响应

时间:2011-06-17 11:31:43

标签: iphone objective-c sqlite uitableview

我的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语句打开数据库。我真的需要这方面的帮助

4 个答案:

答案 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。