5

在向我的应用程序添加新的 Core Data 模型版本后,我执行了轻量级迁移,显然是成功的。迁移的文件加载正常,但在第一次尝试通过特定关系访问属性时,应用程序崩溃并显示NSRangeException: '*** -[__NSArrayM objectAtIndex:]: index 4294967295 beyond bounds [0 .. 35]'. 这种关系在迁移之前运行良好。我从这里的其他帖子中知道 4294967295 确实-1是它的表)。

问题:

我的问题是:根据我遇到的错误和我在下面完成的故障排除,是否有一种模式更改可以通过轻量级迁移,但在此过程中会破坏数据,导致注意到的异常?我将尝试将迁移分解为多个版本的较小块,以隔离或避免该问题,但如果能够专注于可能有问题的特定架构更改,那就太好了。

失败:

失败发生在“myobject”中的以下代码:

[[self object2] text];

object2 关系是一对一的,非可选的两种方式,数据模型之间的正向或反向关系都没有改变。该text属性可能不相关,因为发生错误时,awakeFromFetch在 object2 中未达到。如果我[self object2]在上述语句之前分配给变量,则分配成功并报告data: <fault>.

数据库:

查看 sqlite3 中的数据库,我注意到以下内容:

  1. 正向和反向关系的索引值在每个表中似乎都是正确的。
  2. object2 表有两列用于反向关系,而不是迁移之前的一列(ZMYOBJECT如前所述,另外还有Z2_MYOBJECT一个,对于所有行都是空的)。没有添加其他关系来解释此列。
  3. Z_PRIMARYKEY表中,迁移后的所有条目都显示-1Z_MAX,而在迁移之前,空表显示为零,填充表显示最大行数。手动更新Z_MAX到正确的值对异常没有帮助。所有Z_SUPER值都是正确的。

我建立了一个映射模型,看看自动映射是否有任何问题,但一切看起来都很好。

总体架构更改

在数据模型的源版本中,有 14 个实体,其中只有 4 个已填充数据(该应用程序仍在开发中)。七个是顶级实体,七个是三个顶级实体的子实体。

在数据模型的目标版本中,添加了 22 个实体,一些顶级实体和一些子实体,以及数十种关系,包括一些添加到现有实体中的关系。

从现有实体中删除了一些属性和关系,并添加了其他属性和关系。没有更改数据类型或关系设置,没有重命名属性或关系,也不需要特殊映射。

更新(2/25/12):当我开始研究一个新的中间模型时,我记得我已经将许多实体的类(representedClassName)从 NSManagedObject 更改为 NSManagedObject 子类,但没有生成类文件. 我不怀疑这会导致问题,事实上,创建所有类文件并没有帮助解决异常。我只是想指出这是模型之间的另一个变化。

结论:

这是一个疯狂的猜测,但如果 36 个实体计数不是巧合,似乎当“myobject”试图在“object2”中出错时,它没有对表的有效引用并试图加载表号 -1 ,导致异常。然而,一个简单的分配[self object2]成功的事实并不符合这个结论。

有任何想法吗?

4

3 回答 3

2

通过多次增量迁移,我能够确定导致问题的原因以及解决方案。

问题:

具有数据的现有实体之一在当前模型中没有子实体。如果我创建一个新模型,该模型仅添加一个不包含属性或关系的子实体,并且不进行其他更改,那么我的问题中提到的 NSRangeException、Z_MAX 观察和反向关系的加倍都会发生。

解决方案:

在观察上述案例的“成功”轻量级迁移后的失败后,我创建了一个映射模型。由于唯一的变化是增加了一个实体,因此除了一个实体映射之外,其他所有实体映射都很简单。问题是如何处理单个添加的实体。

默认情况下,添加的没有自己的属性或关系的实体显示所有父级属性的属性和关系映射。默认情况下,所有映射都有空值表达式,我认为这意味着它会在迁移期间跳过它们。显然,这不是真的。通过删除实体映射中的所有属性和关系映射,然后关闭推断映射,迁移成功进行。

我仍然必须处理所有剩余的实体,并将尝试这种方法批量完成其余的工作,所有计划的属性和关系都完好无损。

于 2013-02-26T20:24:39.063 回答
1

当我遇到这个问题时,你的帖子很有帮助。谢谢你。[你已经报告了这个错误吗?]

这里有一些更多的实验结果,但是,唉,这不是一个很好的解决方案。

  • 我的架构更改类似地添加了一个没有其他属性或关系的实体子类型。错误消息与您的相同,但边界为[0 .. 19]. 这确实对应于 20 种实体类型,验证了您的假设。与您的情况一样,在迁移完成后尝试访问实体属性时发生错误。

  • 向新实体类型添加虚拟属性和虚拟自我关系并不能避免迁移后崩溃。(但是,我没有将新实体类型作为唯一的架构更改进行测试,因为我之前将该架构更改推送给了 alpha 测试人员。)

  • 在成功迁移其他架构更改后,我观察了Z2_MYOBJECT列和Z_PRIMARYKEY.Z_MAX = -1症状,因此这些可能根本没有问题。-1 值被适当的最大值懒惰地替换。迁移期间可能会使用额外的列。

  • 在我的例子中,新实体的超类型有一个有序的多对多关系。在整个数据存储仅包含一个对象实例(没有传出关系链接的该实体类型的实例)的非常简单的情况下,模式迁移成功。它确实有额外的Z2_MYOBJECT列和Z_PRIMARYKEY.Z_MAX = -1值,但从那里添加对象时,结果数据存储工作正常。

  • 我尝试创建一个映射模型,但未能成功让 Core Data 应用它。关闭推断映射只会让 Core Data 根本无法迁移。有什么诀窍吗?我是否必须编写自定义迁移代码才能调用映射模型?这是 Xcode 4.6.2,所以旧的错误早已不复存在。

  • 当使用 git 向后或向前滚动代码和数据模型以进行实验时,似乎有必要 (1) 关闭并重新打开 Xcode 项目和 (2) 进行干净的构建。否则 Xcode 可能会崩溃和/或留下混乱的状态。

  • 要实验性地向后滚动,您必须.momd/从目标 iOS 模拟器/设备中删除目录或整个应用程序(或通过 iTunes 或 TestFlight 部署应用程序),因为通过 Xcode 重新部署不会删除过时的文件(如.mom.omo数据模型定义) turn 允许应用程序执行实际部署的应用程序无法执行的轻量级迁移。

  • 关于用于添加的实体类型的实体映射,请注意,当 Core Data 应用映射模型时,它会将实体从旧数据存储复制到新数据存储。它没有修改表。您不希望它“跳过”属性(包括继承的属性),除非您想删除它们。

  • 但是,由于架构更改添加了实体类型,因此该实体没有要迁移的实例,因此其自定义映射模型规则无关紧要。

因此,我想知道是否有其他原因导致您的崩溃停止,例如剩余的实验.mom文件或自定义迁移代码。您的解决方法是否有效?

经过 2 天的试验后,我决定这次我的 alpha 测试人员将不得不在没有数据迁移的情况下生活。幸运的是,这在没有生产客户的情况下发生。但这并没有让我对 Core Data 充满信心。

于 2013-05-17T07:47:52.863 回答
1

NSRangeException在自动轻量级迁移后访问特定实体的任何实例时添加核心数据模型版本后,我有同样的情况。在我的情况下,范围也对应于我模型中的实体数量。

我使用 Xcode 4.6 (4H127) 生成了一个映射模型,File > New > File...然后选择Core Data > Mapping Model. 这导致崩溃(d)演变成-[NSSymbolicExpression length]: unrecognized selector sent to instance...

解决方案

我的问题是导致原始崩溃的实体有一个名为 的关系size,这是苹果的Predicate Programming Guide中列出的保留字。对映射模型的检查显示,保留字在关系的值表达式中已大写:

FUNCTION($manager, "destinationInstancesForEntityMappingNamed:sourceInstances:" , "PNSizeOptionToPNSizeOption", $source.SIZE)

我在Core Data Model Versioning and Data Migration Programming Guide中找到了解决方案:

自定义值表达式中的保留字:如果使用自定义值表达式,则必须使用 # 转义保留字,例如 SIZE、FIRST 和 LAST(例如,$source.#size)。

不幸的是,用于生成映射模型的 Xcode 算法无法识别保留字,我不得不将关系映射检查器中表达式的键路径更改为$source.#size. 这解决了问题。我假设核心数据的推断映射模型在轻量级迁移期间遇到了类似的问题。

这种崩溃可能还有其他原因,因此此解决方案可能不适用,但可能值得根据Predicate Programming Guide中的保留字列表检查模型中的属性名称。

于 2013-06-24T04:54:12.520 回答