iPhone 和 Core Data:如何在更新之间保留用户输入的数据?

Posted

技术标签:

【中文标题】iPhone 和 Core Data:如何在更新之间保留用户输入的数据?【英文标题】:iPhone and Core Data: how to retain user-entered data between updates? 【发布时间】:2010-03-11 02:44:17 【问题描述】:

考虑一个作为动物目录的 iPhone 应用程序。应用程序应该允许用户为每只动物添加自定义信息——比如评分(从 1 到 5 分),以及他们可以输入的关于动物的一些注释。但是,用户将无法修改动物数据本身。假设当应用程序更新时,(静态)目录部分应该很容易更改,但我们希望(动态)自定义用户信息部分在更新之间保留,因此用户不会丢失任何他们的自定义信息。

我们可能希望使用 Core Data 来构建这个应用程序。还假设我们已经有一个先前的过程来读取动物数据以预填充 Core Data 使用的支持 (SQLite) 存储。我们可以将此数据库文件嵌入到应用程序包本身中,因为它不会被修改。当用户下载应用程序的更新时,新版本将包含最新的(静态)动物目录数据库,因此我们不必担心它会过时。

但是,现在棘手的部分是:我们如何以合理的方式存储(动态)用户自定义数据?

我的第一个想法是(动态)数据库应该存储在应用程序的 Documents 目录中,因此应用程序更新不会破坏现有数据。我说的对吗?

我的第二个想法是,由于(动态)用户自定义数据数据库与(静态)动物目录不在同一个存储中,我们不能天真地在 Rating 和 Notes 实体之间建立关系(在一个数据库中) ) 和 Animal 实体(在另一个数据库中)。在这种情况下,我想一种解决方案是在 Rating/Notes 实体中有一个“animalName”字符串属性,并在运行时匹配它。这是最好的方法,还是有办法在 Core Data 中“同步”两个不同的数据库?

【问题讨论】:

@Shaggy Frog...我现在面临同样的问题。我看到您的解决方案是解决此问题的正确解决方案,但我想知道您是否找到了更好的方法来解决此问题。无论如何,感谢您的解决方案。这是迄今为止我找到的最好的帮助。 @user621808 唯一的解决方法是每次更新数据时都不重建数据库。换句话说,只构建一次,然后在需要添加/删除/编辑时手动编辑它。 【参考方案1】:

这基本上是我最终解决这个问题的方法。

虽然 Amorya 和 MHarrison 的回答是有效的,但他们有一个假设:一旦创建,不仅表,而且每个表中的每一行都将始终相同。

问题是我使用现有数据(定期更新)预填充“动物”数据库的过程每次都会创建一个新的数据库文件。换句话说,我不能依赖在 Core Data 中创建(静态)Animal 实体和(动态)Rating 实体之间的关系,因为下次我重新生成应用程序时该实体可能不存在。为什么不?因为我无法控制 Core Data 如何在幕后存储这种关系。由于它是一个 SQLite 后备存储,它很可能正在使用具有外键关系的表。但是,当您重新生成数据库时,您无法假设每行获取某个键的值。如果我在列表中添加了一只狐猴,第二次 Lion 的主键可能会有所不同。

避免此问题的唯一方法是只预先填充数据库一次,然后在每次更新时手动更新行。但是,就我而言,这种过程实际上是不可能的。

那么,解决方案是什么?好吧,既然我不能依赖 Core Data 制作的外键关系,我必须自己编造。我所做的是在我的数据库生成过程中引入一个中间步骤:我没有使用我的原始数据(恰好是 UTF-8 文本,但实际上是 MS Word 文件)并直接使用 Core Data 创建 SQLite 数据库,而是引入了一个中介步骤:我将 .txt 转换为 .xml。为什么选择 XML?好吧,不是因为它是灵丹妙药,而是因为它是一种我可以很容易解析的数据格式。那么这个 XML 文件有什么不同呢?我使用 MD5 为每个 Animal 生成的哈希值,我假设它是唯一的。哈希值有什么用?好吧,现在我可以创建两个数据库:一个用于“静态”动物数据(我已经有一个流程),另一个用于“动态”Ratings 数据库,它是 iPhone 应用程序创建的,位于应用程序的 Documents 目录中.对于每个 Rating,我通过保存 Animal 实体的哈希值来创建与 Animal 的伪关系。因此,每次用户在 iPhone 上打开 Animal 详细视图时,我都会查询“动态”数据库以查找是否存在与 Animal.md5Hash 值匹配的 Rating 实体。

因为我保存了这个中间 XML 数据文件,所以下次有更新时,我可以将它与我用来查看更改的最后一个 XML 文件进行比较。现在,如果一个动物的名字被改变了——假设一个错字被纠正了——我就地恢复那个动物的哈希值。这意味着即使更改了 Animal 名称,我仍然能够在“动态”数据库中找到匹配的 Rating(如果存在)。

这个解决方案还有一个很好的副作用:我不需要处理任何迁移问题。应用程序附带的“静态”动物数据库可以作为应用程序资源嵌入。它可以改变它想要的一切。如果我修改其数据模型以添加更多实体,“动态”评级数据库可能需要迁移,但实际上这两个数据模型保持完全独立。

【讨论】:

【参考方案2】:

我这样做的方式是:将静态资料的数据库作为应用程序包的一部分提供。在应用启动时,检查 Documents 中是否有数据库文件。如果没有,请将应用程序包中的那个复制到 Documents。然后从 Documents 打开数据库:这是您唯一读取和编辑的数据库。

升级后,新的静态内容需要与用户的可编辑数据库合并。每个静态项目(在您的情况下为动物)都有一个名为 factoryID 的字段,这是一个唯一标识符。在更新后的第一次启动时,从应用程序包加载数据库,并遍历每个 Animal。对于每一项,在工作数据库中找到适当的记录,并根据需要更新任何字段。

可能有更快的解决方案,但由于升级过程不会经常发生,因此所花费的时间应该不会太成问题。

【讨论】:

但这要求预填充数据库的进程不能每次都从头开始创建新数据库,对吗?这当然是可能的,但不像该过程不再“无状态”那么简单。【参考方案3】:

将您的 SQLite 数据库存储在 Documents 目录 (NSDocumentDirectory) 中当然是可行的方法。 一般来说,您应该尽可能避免修改或删除 SQL 表的应用程序更改(添加即可)。但是,当您绝对必须在更新中进行更改时,像 Amorya 所说的那样会起作用 - 打开旧数据库,将您需要的任何内容导入新数据库,然后删除旧数据库。

因为听起来您想要一个带有无法修改的“动物”表的静态数据库,所以只需用升级替换此表应该不是问题 - 只要条目的 ID 不改变。您应该存储有关动物的用户数据的方式是为用户创建的每个条目创建与动物 ID 的外键的关系。这是您在升级更改时需要迁移的内容。

【讨论】:

我也遇到了这个问题。我需要了解如何向用户的数据库添加更多行。带有应用程序新增内容的 v2 数据库将被复制以进行新安装,但我需要将新增内容添加到安装 v1 的用户目录中的 sql 数据库中。我怎么做?我已经找了几个星期了,似乎找不到代码来做。

以上是关于iPhone 和 Core Data:如何在更新之间保留用户输入的数据?的主要内容,如果未能解决你的问题,请参考以下文章

iphone数据存储之-- Core Data的使用

如何在 Mac 和 iPhone 之间同步 Core-Data 应用程序?

如何在 iPhone 应用程序之间共享一个 Core Data 模型?

iPhone 上是不是存在 Core Data?或者您将如何在 iPhone 上保存数据?

iPhone如何使用NSPredicate按父实体过滤Core Data?

在 Core Data 存储迁移到新版本时,在 iPhone 应用程序的初始屏幕上显示 MBProgressHUD?