SQLitePlugin 没有提供预填充的数据库。所以目前发生的是您正在打开数据库Documents
,该数据库尚不存在,因此 SQLite 创建并打开一个空数据库。
如果您希望 SQLitePlugin 从资源部分中的现有 SQLite DB 填充数据库,则需要做一些工作才能到达那里。这就是我所做的:(替换中的open
方法SQLPlugin.m
)
/* This is a hacked version which will copy the file from the Resources path
if it does not exist in the Documents path or if it is newer. */
-(void)open: (CDVInvokedUrlCommand*)command
{
CDVPluginResult* pluginResult = nil;
NSMutableDictionary *options = [command.arguments objectAtIndex:0];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *dbname = [self getDBPath:[options objectForKey:@"name"]];
NSValue *dbPointer;
if (dbname == NULL) {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"You must specify database name"];
}
else {
dbPointer = [openDBs objectForKey:dbname];
if (dbPointer != NULL) {
// NSLog(@"Reusing existing database connection");
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"Database opened"];
}
else {
//NSLog(@"Opening %@", dbname );
NSError *error;
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:[options objectForKey:@"name"]];
//NSLog(@"Date in app was %@", [[[fileManager attributesOfItemAtPath:databasePathFromApp error:NULL] fileModificationDate] description]);
//NSLog(@"Local date was %@", [[[fileManager attributesOfItemAtPath:dbname error:NULL] fileModificationDate] description]);
if (![fileManager fileExistsAtPath:dbname]) {
BOOL success = [fileManager copyItemAtPath:databasePathFromApp toPath:dbname error:&error] ;
if (!success) {
NSLog(@"Failed to create writable database file with message '%@'.", [error localizedDescription]);
}
NSLog(@"Database didn't exist in %@, copying it from %@", dbname, databasePathFromApp);
} else if ([[[fileManager attributesOfItemAtPath:databasePathFromApp error:NULL] fileModificationDate] compare:[[fileManager attributesOfItemAtPath:dbname error:NULL] fileModificationDate]] == NSOrderedDescending) {
[fileManager removeItemAtPath:dbname error:NULL];
BOOL success = [fileManager copyItemAtPath:databasePathFromApp toPath:dbname error:&error];
if (!success) {
NSLog(@"Failed to create writable database file with message '%@'.", [error localizedDescription]);
}
NSLog(@"Database in app was newer, copying it from %@", databasePathFromApp);
[[NSURL fileURLWithPath:dbname] setResourceValue: [NSNumber numberWithBool: YES]
forKey: NSURLIsExcludedFromBackupKey error: NULL];
}
const char *name = [dbname UTF8String];
// NSLog(@"using db name: %@", dbname);
sqlite3 *db;
if (sqlite3_open(name, &db) != SQLITE_OK) {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Unable to open DB"];
return;
}
else {
// Extra for SQLCipher:
// const char *key = [[options objectForKey:@"key"] UTF8String];
// if(key != NULL) sqlite3_key(db, key, strlen(key));
// Attempt to read the SQLite master table (test for SQLCipher version):
if(sqlite3_exec(db, (const char*)"SELECT count(*) FROM sqlite_master;", NULL, NULL, NULL) == SQLITE_OK) {
dbPointer = [NSValue valueWithPointer:db];
[openDBs setObject: dbPointer forKey: dbname];
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"Database opened"];
} else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Unable to encrypt DB"];
}
}
}
}
if (sqlite3_threadsafe()) {
NSLog(@"Good news: SQLite is thread safe!");
}
else {
NSLog(@"Warning: SQLite is not thread safe.");
}
[self.commandDelegate sendPluginResult:pluginResult callbackId: command.callbackId];
}
现在,如果您确保已将数据库添加到项目的 Resources 部分(并且还将它们添加到目标的 Build Phases 部分的“Copy Bundle Resources”),则数据库将在必要时从Resources
to复制Documents
。这将返回 Documents 目录中可写数据库的句柄。