【问题标题】:How to update SQLite DB on iPhone app update?如何在 iPhone 应用更新时更新 SQLite DB?
【发布时间】:2011-02-15 14:33:58
【问题描述】:

我目前在 iTunes 应用商店中有一个 iPhone 应用,它使用 SQLite 数据库作为数据存储。用户可以将应用程序与 Web 服务同步,然后将返回的数据存储在 SQLite 数据库中。用户还可以将新项目插入数据库并将其更改同步回网络服务。

当打开到应用程序的本地数据库的连接时,代码会检查以确认数据库文件是否存在于“Documents”文件夹中,如果不存在,则通过将数据库从“Resources”文件夹复制到“文档”文件夹。

我必须发布应用程序的更新。更新包含数据库架构更改(新表、列等)。根据我的阅读,“文档”目录中的文件将在应用程序更新时保留,这意味着现有数据库在更新后仍将完好无损。

我的问题是,如何用我更新的数据库替换现有的数据库,有没有办法在不丢失现有数据库中的数据的情况下这样做?是否可以使用某种“更新后首次运行”事件来进行数据库更新,或者我是否必须对现有数据库进行某种检查(查找新列或表),如果我的检查失败手动替换/更新数据库?

谢谢!

【问题讨论】:

标签: iphone objective-c sqlite


【解决方案1】:

您应该将应用程序的当前版本号永久存储在数据库中,或者更好的是在默认数据库中。启动时,您的应用会将其自己的版本号与持久的版本号进行比较。如果它们不同,那么这是更新后的第一次运行。如果没有持久化的版本号,那么显然这也是更新后的第一次运行。

至于更新您的数据库,如果它已经到位,您将使用通常的 SQL ALTER 命令来更新您的架构,并同时进行任何数据库数据迁移。

【讨论】:

  • 所以没有内置的“应用程序更新”或“更新后首次运行”事件/检查或类似的东西?听起来我必须在每次应用加载时检查版本?
  • 我不知道,但如果有的话,在文档中很容易找到...
【解决方案2】:

sqlite3 *数据库; sqlite3_stmt *update_statement = nil;

if(sqlite3_open([strDatabasePath UTF8String], &database) == SQLITE_OK)
{
   nsstring  *strMQueryupdate="write your query here";

    const char *sql = [strMQueryupdate UTF8String];

    if (sqlite3_prepare_v2(database, sql, -1, &update_statement, NULL) != SQLITE_OK) {
        NSLog(@"update fails");
    }
    else
    {
        sqlite3_bind_text(update_statement, 1, [[arrayname objectAtIndex:0]  UTF8String], -1, SQLITE_TRANSIENT);


        int success = sqlite3_step(update_statement);
        sqlite3_reset(update_statement);
        if (success == SQLITE_ERROR){}
        else {}
    }
    sqlite3_finalize(update_statement);
}
sqlite3_close(database);   

【讨论】:

    【解决方案3】:

    我们通过向服务器查询 plist 标头中的哈希值来检查更新,该哈希值通过查询服务器数据库的 php 文件输出。您可以在本地存储该哈希并将其与应用程序上次运行的时间进行比较。这样手机就知道它的版本是否过时了。然后我们在后台下载新的plist,更新手机上的数据库。

    编辑:

    在我们的 php 结束时,我们得到了我们在服务器上生成的 plist 的 XML 输出的 MD5,如下所示:

    header("MD5-Hash: ". md5($xml_output));
    echo $xml_output;
    

    然后我们从 userDefaults 中获取 iPhone 上 plist 的哈希值,如下所示:

    NSUserDefaults* defaults  = [NSUserDefaults standardUserDefaults];
    curHash = [defaults stringForKey:kUpdateUserDefault];
    

    以及来自 NSURLRequest 的服务器哈希,如下所示:

    NSString *hash = [[[res allHeaderFields] objectForKey:kUpdateHeaderField] retain];
    

    然后我们比较两者,只有当哈希不匹配时才开始下载:

        if (![curHash isEqualToString:hash]) {
                [self performSelector:@selector(sendUpdateStarted) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO];
                ... download the file and save it as the new iPhone's plist
        }
    

    此代码由我非常有能力的合作伙伴 Oliver Rice 编写。

    【讨论】:

    • 我不太明白你的回答。什么 plist 的哈希?
    • 这似乎还有防止盗版的额外好处。
    • 关于防止盗版,它不会阻止某人访问您服务器的 plist 并获取该信息,除非您发送手机的 UUID 并在首次加载应用程序时存储该信息。如果您想密封文件,这可以让您在将数据提供到服务器的 plist 之前进行一些测试。
    • [self performSelector:@selector(sendUpdateStarted) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO]; 应该写成[self performSelectorOnMainThread:@selector(sendUpdateStarted) withObject:nil waitUntilDone:NO];
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-07
    • 1970-01-01
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    相关资源
    最近更新 更多