我在sqlite上遇到了一个奇怪的问题,这让我抓狂。
我在我的应用程序中实现了一个sqlite数据库,当我通过xcode启动应用程序时,一切都很好。在模拟器和我的ipad上。但是,当我构建一个特别版本并在ipad上安装该特别版本时,该应用程序在尝试启动时崩溃,因为它没有从sql数据库中获取数据,因为数据库中没有数据。在第一次启动时,应用程序应该使用从xml文件中获取的数据初始化数据库,然后仅通过sqlite数据库访问数据。如果从xcode运行,效果很好,但如果从特别版本运行,效果就不好。
有人知道为什么会这样吗?我该如何解决这个问题?如果需要源代码,我会提供。
数据库文件包含在捆绑包中,即使没有,也会创建它。
Thx,Maverick1st
现在我在我的应用程序中这样做DidFinishLaunchingWithOptions
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
[AppState sharedInstance].s_databasePath = [documentsDir stringByAppendingPathComponent:[AppState sharedInstance].s_databaseName];
if ([self checkForSQLiteDataBaseFile])
{
if (![self checkForSQLiteDataBaseTable]) {
[self loadDataFromXMLIntoNSDictionary];
}
}
-(BOOL) checkForSQLiteDataBaseFile
{
BOOL ret = NO;
// Check if the SQL database has already been saved to the users phone, if not then copy it over
// Create a FileManager object, we will use this to check the status
// of the database and to copy it over if required
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check if the database has already been created in the users filesystem
// If the database already exists then return without doing anything
if([fileManager fileExistsAtPath:[AppState sharedInstance].s_databasePath])
{
Log2(@"databasePath: %@", [AppState sharedInstance].s_databasePath);
ret = YES;
return ret;
}
// If not then proceed to copy the database from the application to the users filesystem
// Get the path to the database in the application package
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:[AppState sharedInstance].s_databaseName];
// Copy the database from the package to the users filesystem
[fileManager copyItemAtPath:databasePathFromApp toPath:[AppState sharedInstance].s_databasePath error:nil];
Log2(@"databasePath: %@", [AppState sharedInstance].s_databasePath);
ret = YES;
return ret;
}
这是我的文档路径:数据库路径:/var/mobile/Applications/0CE5F143-04AC-4E1C-9A94-2B253F86F854/Documents/KatalogDaten
我还发现,我的数据库是由sqlite打开的,因为以下语句是正确的:
if(sqlite3_open([[AppState sharedInstance].s_databasePath UTF8String], &database) == SQLITE_OK)
*编辑**在用iExplorer检查了ipad上应用程序的文件系统后,我注意到表确实在那里,而且本身也有内容。但由于我在应用程序中处理虚拟表,因为我需要全文搜索,所以我想创建一个虚拟表,如果该数据库中不存在虚拟表,并且似乎以某种方式失败了。如果我发现更多,我会提供进一步的更新。
**编辑***
所以,我想我发现了错误在哪里,但不是什么原因造成的。
以下源代码正常执行,但仅在从我的ipad上的xcode运行时返回所需结果,而不是在从我ipad上的特别版本运行时返回。
if(sqlite3_open([[AppState sharedInstance].s_databasePath UTF8String], &database) == SQLITE_OK)
{
NSLog(@"Database opened successfully!");
const char *sqlQuery = [@"select DISTINCT tbl_name from sqlite_master where tbl_name = ?;" UTF8String];
Log2(@"sqlquery for selecting distinct table: %s", sqlQuery);
sqlite3_stmt *compiledQuery;
if(sqlite3_prepare_v2(database, sqlQuery, -1, &compiledQuery, NULL) == SQLITE_OK)
{
sqlite3_bind_text(compiledQuery, 1, [k_db_virtualTableName UTF8String], -1, SQLITE_TRANSIENT);
if(sqlite3_step(compiledQuery))
{
// look if virtual table already exists
if ((char *)sqlite3_column_text(compiledQuery, 0) == nil)
{
NSLog(@"Create virtual table!");
sqlite3_finalize(compiledQuery);
sqlQuery = [[NSString stringWithFormat:@"CREATE VIRTUAL TABLE %@ USING FTS3 (%@);", k_db_virtualTableName, keyString] UTF8String];
Log2(@"sqlQuery: %s", sqlQuery);
if(sqlite3_prepare_v2(database, sqlQuery, -1, &compiledQuery, NULL) == SQLITE_OK)
{
NSLog(@"query for virtual table is ok!");
if(sqlite3_step(compiledQuery))
{
NSLog(@"query for virtual table was executed properly!");
sqlite3_finalize(compiledQuery);
[self fillSQLiteDataBaseTable: k_db_virtualTableName WithDataFromDict: [[[xmlDictionary objectForKey:@"UHRENTABELLE"] objectForKey:@"UHR"] mutableCopy]];
}
else
{
sqlite3_finalize(compiledQuery);
}
}
}
else
{
NSLog(@"Virtual Table already exists!!");
sqlite3_finalize(compiledQuery);
}
}
}
else
{
NSLog(@"The following statement is not correct: %@", sqlQuery);
}
}
sqlite3_close(database);
当通过xcode或从特定版本运行时,方法fillSQLiteDataBaseTable
也会正常执行。唯一的区别是,在ad-hoc版本中,虚拟表的创建会在应用程序不告诉我的情况下失败。应用程序会继续运行,就好像什么都没发生一样,但当我之后查看sql文件时,从ad-hoc版运行时,那里没有虚拟表。虚拟表仅在从xCode运行时存在。
嗯。。如果文件在您的资源包中,请不要在该文件上进行写入。。您应该首先在应用程序的文档目录中复制一个空白数据库。。那么你应该写在那个文件里。。如果您签署了应用程序,apple-sdk不允许更改nsbundle中的任何内容。。
以下是如何在文档目录-中获取数据库的路径
NSString *documentsDir = [CommonFunctions documentsDirectory];
databasePath = [[documentsDir stringByAppendingPathComponent:@"yourdatabase.sqlite"] retain];
[self checkAndCreateDatabase];
在获得此路径后,您应该检查数据库是否已经存在(然后确定…)如果不存在,则使用下面的函数将空白数据库从nsbundle复制到文档目录-
//check if database exists else copy
-(void) checkAndCreateDatabase
{
// Check if the SQL database has already been saved to the users phone, if not then copy it over
BOOL success;
// Create a FileManager object, we will use this to check the status
// of the database and to copy it over if required
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check if the database has already been created in the users filesystem
success = [fileManager fileExistsAtPath:databasePath];
// If the database already exists then return without doing anything
if(success) return;
// If not then proceed to copy the database from the application to the users filesystem
// Get the path to the database in the application package
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"yourdatabase.sqlite"];
// Copy the database from the package to the users filesystem
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
}
如果你需要更多的帮助,请发表评论。
我忘记在sqlite.c文件的头部添加以下行
#define SQLITE_ENABLE_FTS3
所以,当我从xcode运行我的版本时,基本上就是问题所在。使用了我的捆绑包中的sqlite版本,它似乎支持fts3,出于某种原因,我不知道是否需要使用该定义来启用它。
不过,我的iPad上的sqlite版本不支持fts。所以这可能就是我的sqlite行为如此奇怪的原因。
无论如何。现在它运行得非常平稳。