【问题标题】:Removing and adding persistent stores to a core data application删除和添加持久存储到核心数据应用程序
【发布时间】:2011-01-16 11:39:09
【问题描述】:

我在 iPhone 应用程序上使用核心数据。我有多个持久性商店,我正在从一个切换到另一个,因此当时只有一个商店可以处于活动状态。我有一个托管对象上下文,不同的持久存储在数据格式(sqlite)上相似,并且共享相同的托管对象模型。

我正在将数据从各自的 XML 文件导入到每个持久性存储中。第一次导入一切正常,但是在我删除导入的数据(持久存储和物理文件)然后重新导入后,核心数据给了我一个错误:

*** Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'The NSManagedObject with ID:0x3c14e00 <x-coredata://6D14F11E-2EA7-4141-9BE8-53747DE6FCC6/Book/p2> has been invalidated.'

此错误来自 NSManagedObjectContext 的保存:在重新导入之前,我正在从持久存储协调器中删除持久存储并删除物理文件,所以一切都应该就像第一次完成重新导入一样。此外,托管对象上下文中的对象被删除,上下文被发送 reset: 消息(我不知道这是否真的需要)。

有人可以帮我吗?持久化存储应该如何切换?

我基本上使用与此处辅导相同的逻辑:http://blog.sallarp.com/iphone-core-data-uitableview-drill-down/

提前致谢。

目标更新

感谢您的回答。

抱歉,我的目标含糊不清。我正在开发一个圣经阅读器应用程序,它将从 XML 导入核心数据 SQL 的翻译。目前只能使用一种翻译。目前我对每个翻译只有不同的 MOC 和 PS,因为模型是相同的。但是,如果您说应该将堆栈作为一个整体创建,我确实相信。翻译之间没有联系,因此没有实际理由使用相同的堆栈。唯一可能使这复杂化的是注释/书签/等将引用活动翻译。但是,引用将是文本的,因此再次不需要共享堆栈。

感谢您的意见。

【问题讨论】:

  • 创建一个新的上下文解决了这个问题。我不得不通过将两个参数、持久存储和托管对象上下文传递给导入器实例来更改一些逻辑,这最终是我发现关于可可通知的一件非常好的事情。无论如何,我要去寻找新的问题。再次感谢你们。

标签: iphone cocoa-touch core-data


【解决方案1】:

我同意 Louis 的观点,你所做的是一个危险的设计,你应该重建整个堆栈,而不是像那样换掉商店。重建整个堆栈并不是一个巨大的开销。

另外,如果您使用完全不同的模型和完全不同的数据对象,您不需要删除它们,您可以将所有模型一起添加到一个持久存储中,并根据您创建的实体,Core Data 会做正确的事情。

如果您使用相同实体构建多个模型,那么问题是为什么?您不会从中获得任何性能优势。

更新

在您描述的情况下,我会将所有存储放入单个持久存储协调器中,然后指示上下文哪个存储使用-assignObject:toPersistentStore: 保存实体。这将消除建立和拆除多个核心数据堆栈的需要。

更新 2

一个新的堆栈是整个堆栈。 PSC、MOM 和 MOC。您正在从核心数据堆栈下拉出地毯,然后期望它能够弄清楚您在做什么。

你的最终目标是什么?

延迟更新

嗯,那么仅创建 PS 和 MOC 并使用现有的 PSC 和 MOM 的可接受方案是什么?如果我猜到了,我会说每次对现有堆栈进行修改时,都应该重新创建它,如果使用多个商店,则应该在构建时引入它们。

NSManagedObjectModelNSPersistentStoreCoordinatorNSPersistentStore 紧密相连,因此不清楚您的目标是什么。如果你用你想要完成的事情来更新你的问题,它会让答案变得不那么模糊。

拥有多个NSManagedObjectContext 实例通常用于处理多个线程和一些非常罕见的边缘情况。拥有多个 NSPersistentStore 实例时,通常会使用由于某种原因(部分只读等)需要存储数据的数据。这些是正常的用例。

我的问题仍然存在,你想完成什么?

目标更新

我正在开发一个圣经阅读器应用程序,它将从 XML 导入核心数据 SQL 的翻译。目前只能使用一种翻译。

好的,您不需要为每个翻译单独的文件,那是浪费。由于每个翻译都由代码(例如 ASM)和名称、版权等标识,因此您可以在设计中简单地创建一个名为...“翻译”的顶级实体,其余数据从那里分支。没有多个上下文,没有切换,它只是工作。

您需要多个文件的唯一情况是您处于多文档设计中,这不是您在 iPhone 上所做的事情。

【讨论】:

  • 正如我已经回复路易斯的那样,我正在尝试实现一种在物理存储之间切换的方法,每个物理存储都包含不同的翻译。我知道托管对象上下文可以在翻译之间共享,但显然为每个翻译使用不同的上下文会更安全。这种方式会不会危险一些?重建堆栈是否也意味着新的持久存储协调器?如果我理解正确,我只需要创建一个新的上下文并将它们一起存储和使用。感谢您的意见。
  • 响应 Update2:基本上我正在做的是在相同模型的相同源的不同翻译之间切换。稍后我可能有多个持久性存储,每个翻译一个,但现在我只会将它们作为导入文件。我应该为每个翻译单独创建堆栈吗?不过,他们将共享相同的 MOM。再说一次,我不是在尝试优化,我只是在尝试简化事情。
  • 嗯,那么仅创建 PS 和 MOC 并使用现有 PSC 和 MOM 的可接受方案是什么?如果我猜到了,我会说每次对现有堆栈进行修改时,都应该重新创建它,如果使用多个商店,则应该在构建时引入它们。
  • 我是 Stack Overflow 的新手,不知道是否通知了问题的更新,但我添加了对“延迟更新”的回复。为混乱的回答道歉,我总是不确定在哪里回复。
  • 您确定将每个翻译存储到同一个文件时没有性能问题吗?我的意思是,一份翻译将消耗大约 5 到 10 兆字节。当时(当前)只有一个翻译处于活动状态,并且很少进行存储的交换。如果是这样,如果我将翻译文件分开,我应该在完全不同的堆栈(MOM、PSC、PS 和 MOC)中处理它们吗?
【解决方案2】:

几乎可以肯定的是,您使用的 NSManagedObjectContext 仍然具有对由分离的持久存储支持的对象的内部引用。处理此问题的最简单方法是不重用上下文。

我不清楚为什么要重用相同的持久存储协调器或托管对象上下文。如果这些确实是概念上独立的一组事物(这样您一次只能使用一个),您为什么要尝试重用其中可能存在陈旧状态的现有堆栈(这就是导致您的问题的原因)。

创建和销毁 NSManagedObjectContexts 真的很轻量级。创建一个全新的 PSC 有点繁重,但就您正在做的事情(移动文件和导入 XML)而言,它可能也无法衡量。

【讨论】:

  • 感谢您的回答。我不明白的是,如果它被清空并重置并且我要添加新的,为什么上下文中会留下任何实体。我对 obj-c/cocoa 很熟悉,很抱歉有任何混淆。我现在不打算重用或保存任何资源,因为这种情况很少发生。基本上我会有不同的翻译,但目前我只使用一种。如果不需要,我不想限制任何东西。那么在这种情况下,为不同的翻译使用不同的上下文会更好吗?但是,上下文将共享相同的模型。
猜你喜欢
  • 2011-08-11
  • 1970-01-01
  • 1970-01-01
  • 2016-12-22
  • 1970-01-01
  • 2012-12-15
  • 1970-01-01
  • 2012-03-24
  • 2012-12-20
相关资源
最近更新 更多