我已经在线阅读了各种关于在ios中处理sqlite3数据库的教程,特别是我已经阅读过" Ray Wenderlich"教程和阅读这里的许多查询,但我不明白为什么我的代码不起作用。
我有一个看似打开的简单数据库。它有一个包含200个多项选择题的表格。我试图选择所有答案,查询并不复杂,并且可以在sqlitebrowser中使用。
我也已将libsqlite3.dylib
添加到项目中,否则数据库的打开将无法正常工作。我确信这是一个非常简单的修复方法,但在查看代码后我无法看到它:
@implementation QuizController
sqlite3 *db;
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"Hello Quiz");
NSString *p = [self filePath];
[self openDB];
NSString *query = @"SELECT answer from questions";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, [query UTF8String], -1, &statement, NULL)
== SQLITE_OK) {
NSLog(@"SQLITE PREPARED OK!");
while (sqlite3_step(statement) == SQLITE_ROW) {
NSLog(@"YES");
}
}
else{
NSLog(@"sqlite prepare failed");
}
}
//file path to db
-(NSString *) filePath {
NSLog(@"pathtest");
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[paths objectAtIndex:0] stringByAppendingPathComponent:@"questionsDb.sqlite"];
}
//open the db
-(void)openDB {
NSLog(@"opentest");
if (sqlite3_open([[self filePath] UTF8String], &db) !=SQLITE_OK) {
NSLog(@"%d", sqlite3_open([[self filePath] UTF8String], &db));
sqlite3_close(db);
NSLog(@"Database failed to open");
} else {
NSLog(@"database opened");
}
}
我看到的日志输出是:
2014-10-16 20:52:01.627 QuizTemplate[15963:802498] pathtest
2014-10-16 20:52:01.627 QuizTemplate[15963:802498] opentest
2014-10-16 20:52:01.628 QuizTemplate[15963:802498] pathtest
2014-10-16 20:52:01.648 QuizTemplate[15963:802498] database opened
2014-10-16 20:52:01.649 QuizTemplate[15963:802498] sqlite prepare failed
答案 0 :(得分:1)
更改您的" sqlite准备失败"包括sqlite3_errmsg
:
NSLog(@"sqlite prepare failed: %s", sqlite3_errmsg(db));
毫无疑问,它会告诉你表格不存在。
这是因为您的打开例程只是打开文档文件夹中的数据库,如果不存在,则会创建一个空白数据库。 (如果找不到文件,那就是sqlite3_open
的作用。)
你可能想要:
从您的设备/模拟器中卸载应用程序,以删除可能存在的任何空白数据库。
您想要调用将在文档中查找数据库的例程,如果找不到,请将其从包中复制到Documents:
- (void) installDatabaseIfNeeded {
// Get the documents database path
NSString *documentsFolder = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *documentsDatabasePath = [documentsFolder stringByAppendingPathComponent:@"test.sqlite"]; // always use setter when setting property's value
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:documentsDatabasePath]) {
// if the database doesn't exist in documents, look for it in the bundle and copy it if found
NSString *bundleDatabasePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"sqlite"];
if (bundleDatabasePath) {
NSError *error;
if (![fileManager copyItemAtPath:bundleDatabasePath toPath:documentsDatabasePath error:&error]) {
NSLog(@"copyItemAtPath failed: %@", error);
}
}
}
}
显然,请更改bundleDatabasePath
和documentsDatabasePath
中引用的文件名,但希望这说明了这一概念。
如果您仍然遇到问题,还有一些额外的想法:
使用sqlite3_open
选项将sqlite3_open_v2
的所有来电替换为SQLITE_OPEN_READWRITE
。如果我们省略SQLITE_OPEN_CREATE
选项,如果它找不到它,显然不会创建空白数据库。让我们消除这种可能性。因此:
- (void)openDB {
NSLog(@"opentest");
int rc = sqlite3_open_v2([[self filePath] UTF8String], &db, SQLITE_OPEN_READWRITE, NULL);
if (rc != SQLITE_OK) {
NSLog(@"open failed: %d", rc);
NSLog(@"Database failed to open");
} else {
NSLog(@"database opened");
}
}
再次删除该应用并重新安装。 (不要只是做一个"干净的构建",但实际上是从设备/模拟器中删除应用程序。)
构建应用程序并将其安装在模拟器上。现在检查包中的数据库:
打开模拟器的设备文件夹;
在Mac OS文件系统中找到您的应用(位于Xcode 6之前的Xcode版本~/Library/Application Support/iPhone Simulator
下方,Xcode 6中为~/Library/Developer/CoreSimulator/Devices
);
打开应用程序包(右键单击它并选择"显示包内容");
在捆绑中查找数据库副本;以及
在您选择的数据库工具中打开它。确保您的表实际存在于数据库的副本中,并且名称是正确的。
有时,Xcode会对包中的内容(特别是使用外部编辑的文件,如SQLite数据库)感到困惑,这可以通过删除派生数据文件夹来解决。或者您可能拥有数据库的多个副本,而忽略了更新Xcode项目中的数据库。
这可能是很多事情,所以通过检查捆绑中的真实内容,它将确定问题的根源。