我的模拟器运行良好而快速。我试图创建和填充数据库时,我的iphone似乎冻结了。但是我更喜欢使用模拟器中的数据库并将其放在iphone上,这样用户就不必重新创建数据库了。 我想知道的是如何从添加到文件夹的数据库中加载。
我搜索了很多但是它已经过时或者与我想要的不同。 我现在将数据库文件从finder添加到xcode项目中。 所以,如果我是正确的,我必须将_databasePath更改为指向文件所在的位置,我是否正确?
如果是这样,那么代码中的那个就在这里: /var/mobile/Applications/65B5541A-1E73-46F6-AB5A-C5988003103E/Documents/paths.db 但那不是我拖入xcode的人。 我也看了组织者,我可以看到文件/ paths.db,但由于它错过了其他文件我也假设这是代码创建db而不是拖入。 我试图删除它,但我无法选择它。
有人可以帮忙吗? 标题中的:
@property (strong, nonatomic) NSString *databasePath;
@property (nonatomic) sqlite3 *pathDB;
in .m:
- (void) createDataBaseIfNotExist {
NSString *docsDir;
NSArray *dirPaths;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
// Build the path to the database file
_databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent:@"paths.db"]];
NSLog(@"databasePath: %@", _databasePath);
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: _databasePath] == NO) {
const char *dbpath = [_databasePath UTF8String];
if(sqlite3_open(dbpath, &_pathDB) == SQLITE_OK) {
char *errMsg;
const char *sql_stmt =
"CREATE TABLE IF NOT EXISTS Paths (ID INTEGER PRIMARY KEY AUTOINCREMENT, START INTEGER, END INTEGER, DISTANCE REAL, NODES TEXT)";
if (sqlite3_exec(_pathDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
//_status.text = @"Failed to create table";
NSLog(@"Failed to create table");
}
sqlite3_close(_pathDB);
} else {
// _status.text = @"Failed to open/create database";
NSLog(@"Failed to open/create database");
}
}
}
答案 0 :(得分:1)
所以,有几件事:
如果createDatabaseIfNotExist
中找不到Documents
,则首先需要修改要从包中复制的- (void) createDataBaseIfNotExist {
// Get the documents database path
NSString *docsDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
self.databasePath = [docsDir stringByAppendingPathComponent:@"paths.db"]; // always use setter when setting property's value
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:_databasePath] == NO) {
// if the database doesn't exist in documents, look for it in the bundle and copy it if found
// get the bundle database path
NSString *bundleDatabasePath = [[NSBundle mainBundle] pathForResource:@"paths" ofType:@"db"];
if (bundleDatabasePath) {
// if we successfully copied from bundle, then quit
if ([fileManager copyItemAtPath:bundleDatabasePath toPath:self.databasePath error:nil])
return;
}
// otherwise, let's proceed with creating the database
if(sqlite3_open([_databasePath UTF8String], &_pathDB) == SQLITE_OK) {
char *errMsg;
const char *sql_stmt = "CREATE TABLE IF NOT EXISTS Paths (ID INTEGER PRIMARY KEY AUTOINCREMENT, START INTEGER, END INTEGER, DISTANCE REAL, NODES TEXT)";
if (sqlite3_exec(_pathDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK) {
//_status.text = @"Failed to create table";
NSLog(@"Failed to create table, %s", errMsg);
sqlite3_free(errMsg); // if you're going to use that fifth parameter, you must free it when you're done
}
sqlite3_close(_pathDB);
} else {
// _status.text = @"Failed to open/create database";
NSLog(@"Failed to open/create database");
}
}
}
:
Documents
其次,在模拟器上运行一次后,在模拟器的XXX
文件夹中找到Xcode项目的数据库。模拟器的文件可以在
〜/ Library / Application Support / iPhone Simulator / 6.1 / Applications / XXX / Documents
其中85206BA6-9D03-4F18-BB0A-3B8C25B552C4
是神秘的标识符(例如Library
)。请注意,默认情况下,configuration
文件夹是隐藏的,因此我转到终端命令行并输入以下命令来显示它:
chflags nohidden Library
然后,您可以通过从Finder拖动到Xcode的文件导航窗口将数据库添加回项目,此时您将看到如下窗口:
请务必检查两个突出显示的复选标记,以确保数据库将包含在捆绑包中。
最后两次观察:
现在您已经拥有了“必要时从包中复制逻辑”,这是一个有趣的问题,您是否真的希望代码在代码中再创建表。就个人而言,我总是用一个漂亮的Mac图形SQLite工具创建我的数据库,然后将它们复制到我的项目中。我编程创建表的唯一时间是(a)我正在部署涉及新/更改表的更新; (b)用户的数据库可能包含一些我不想简单地用捆绑包中的数据库替换的关键数据。
我个人总是在我的应用中包含一个{{1}}表,其中包含一行,其中一列是数据库版本。因此,我的应用程序将从文档打开数据库,检查版本号,如果过期(因为用户刚刚刚刚升级了他们的应用程序),然后更新数据库。这个“数据库版本号”逻辑是您真正希望作为应用程序版本1.0的一部分实现的。