1

我的模拟器运行良好且快速。我的 iphone 似乎在我尝试创建和填充数据库的部分冻结。但是我更喜欢使用模拟器中的数据库并将其放在 iphone 上,这样用户就不必重新创建数据库。我想知道的是如何从添加到文件夹的数据库中加载。

我搜索了很多,但要么它已经过时,要么与我想要的不同。我现在将数据库文件从 finder 添加到 xcode 项目中。因此,如果我是正确的,我必须更改 _databasePath 以指向文件所在的位置,对吗?

如果是这样,它在哪里,代码中的那个在这里:/var/mobile/Applications/65B5541A-1E73-46F6-AB5A-C5988003103E/Documents/paths.db 但这不是我拖入xcode的那个。我还查看了管理器,我可以看到文档/paths.db,但由于它错过了其他文件,我还假设这是创建数据库的代码,而不是拖入的代码。我也尝试删除它,但我无法选择它。

有人可以帮忙吗?

在标题中:

@property (strong, nonatomic) NSString *databasePath;
@property (nonatomic) sqlite3 *pathDB;

以 .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");
        }
    }

}
4

1 回答 1

1

所以,有几件事:

  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");
            }
        }
    }
    
  2. Documents其次,一旦你在模拟器上运行了一次,在你的 Xcode 项目的模拟器文件夹中找到数据库。模拟器的文件可以在

    ~/Library/Application Support/iPhone Simulator/6.1/Applications/XXX/Documents

    哪里XXX是神秘的标识符(例如85206BA6-9D03-4F18-BB0A-3B8C25B552C4)。请注意,默认情况下,该Library文件夹是隐藏的,因此我转到终端命令行并键入以下命令以显示它:

    chflags nohidden 库
    
  3. 然后,您可以通过从 Finder 拖动到 Xcode 的文件导航器窗口,将数据库添加回您的项目,此时您将看到如下窗口:

    在此处输入图像描述

    确保选中两个突出显示的复选标记以确保数据库将包含在包中。

最后的两个观察:

  • 既然您有了“必要时从捆绑包复制的逻辑”,那么您是否真的希望代码再用代码创建表是一个有趣的问题。就个人而言,我总是用一个漂亮的 Mac 图形 SQLite 工具创建我的数据库,然后将它们复制到我的项目中。我唯一一次以编程方式创建表是(a)我正在部署涉及新/更改表的更新;(b) 用户的数据库可能包含一些我不想简单地用捆绑包中的数据库替换的关键数据。

  • 我个人总是configuration在我的应用程序中包含一个表,其中包含一行,其中一列是数据库版本。因此,我的应用程序将从文档中打开数据库,检查版本号,如果已过期(因为用户刚刚升级了他们的应用程序)然后更新数据库。这种“数据库版本号”逻辑是您真正希望作为应用程序 1.0 版的一部分而到位的东西。

于 2013-05-04T15:38:55.487 回答