2013-02-23 147 views
5

将新的Core Data模型版本添加到我的应用后,我执行了轻量级迁移,显然已成功完成。迁移后的文件加载正常,但在第一次尝试通过特定关系访问属性时,该应用程序崩溃,出现NSRangeException: '*** -[__NSArrayM objectAtIndex:]: index 4294967295 beyond bounds [0 .. 35]'。这种关系在迁移之前运行良好。我从其他帖子了解到,4294967295确实是-1,但我可以在我的应用/数据中识别出36个项目的唯一情况是数据模型中有36个实体(作为参考,正在获取的关系有58个项目在其表格中)。核心数据迁移后的NSRangeException

问题:

我的问题是:根据我得到的错误,我已经做了以下的故障排除,有没有一种模式的变化,可以通过轻量级迁移,但腐败一路上的数据,导致着名的例外?我将尝试将几个版本的迁移划分为更小的块,以便隔离或避免该问题,但能够专注于可能存在错误的特定模式更改会很好。

失败:

用下面的代码中的“为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值都是正确的。

我设置了一个映射模型来查看是否有任何东西看起来与自动映射有关,但一切看起来都很好。

总体架构更改

在数据模型的源代码版本,有共有十四实体,其中只有四个已经填充了数据(应用程序仍处于开发阶段)。 7个是顶级实体,7个是三个顶级实体的子实体。

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

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

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

结论:

这是胡乱猜测,但如果36单位数是不是巧合,似乎在“为MyObject”试图在“对象2”故障它没有一个有效的参考对于表并且试图加载表号-1,导致异常。然而,简单的[self object2]赋值成功的事实并不符合该结论。

任何想法?

回答

2

通过多次增量迁移工作,我能够确定是什么导致了问题和解决方案。

问题:

一个现有实体的数据在当前的模型没有子实体。如果我创建了一个简单地添加一个子实体的新模型,它不包含任何属性或关系,并且没有其他更改,那么NSRangeException,Z_MAX观察和我的问题中记录的相反关系的翻倍都会发生。

解决方案是:

观察以下对上面的情况是“成功的”轻量迁移失败后,我创建映射模型。由于唯一的变化是一个额外的实体,除了一个实体映射外,其他所有实体都是直接的。问题是如何处理单个附加实体。

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

我仍然必须解决所有剩余的实体,并将尝试使用此方法批量执行其余所有计划的属性和关系。

+0

你是如何选择你的映射模型的?关闭自动迁移后? – 2013-07-03 09:12:58

+0

@JoãoNunes一旦禁用了自动迁移,只要源和目标散列匹配,它就会自动选择您的映射模型。只要您在创建映射模型后尚未修改数据模型,它们就应该匹配。不幸的是,有时他们不这样做,正如这里所说:(http://stackoverflow.com/questions/10894383/core-data-mapping-model-version-hashes-not-matching-to-source-model-version-hash )。打开核心数据迁移调试模式可以帮助解决未选择映射模型的问题。 – 2013-07-03 15:56:28

+0

感谢您的提示。我为迁移添加了调试,但仍然存在问题。我在这里创建了一个问题:http://stackoverflow.com/questions/17464414/core-data-mapping-model-not-working-with-correct-hashes – 2013-07-04 07:50:55

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,所以旧的bug早已消失。

  • 当使用GIT中向后或向前滚动码&数据模型进行实验,这似乎是必要的:(1)关闭&重新打开Xcode项目和(2)做一个干净的构建。否则Xcode可能会崩溃和/或离开混淆状态。

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

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

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

因此我不知道别的东西造成的死机停下来,像吃剩的实验.mom文件或自定义的迁移代码。你的解决方法是否成立?

经过2天的试验,我决定我的阿尔法测试人员必须在这次没有数据迁移的情况下生活。幸运的是,这没有生产客户。但它并没有让我对Core Data有信心。

+0

感谢您的补充信息。在解决了这里提到的问题之后,根据我的回答,我遇到了另一个引起我注意的反复出现的问题:(http:// stackoverflow。COM /问题/ 10894383 /核心数据映射模型版本哈希值 - 不匹配 - 源模型版本哈希)。提供给这个问题的答案并没有解决我的问题,所以我增加了一个赏金,但没有得到任何回应。我没有报告错误,因为我希望上个月在本地Cocoa会议上参加核心数据会议,看看专家是否知道解决方案。不幸的是,我无法参加。 – 2013-05-22 18:02:15

+0

通常,您不需要编写自定义迁移代码,但有几件事情可能会阻止映射模型正常工作。我在上面的评论中提到了一个关联的问题。您需要检查映射模型中的哈希值与源数据文件和活动模型版本中的哈希值。查看这个问题的答案,以获取有关启用Core Data调试的详细信息,如果尚未这样做:http://stackoverflow.com/questions/12835950/debug-core-data-migration-to-compare-hash-values – 2013-05-22 18:07:34

1

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

我使用File > New > File...,然后选择Core Data > Mapping Model,生成了Xcode 4.6(4H127)的映射模型。这导致崩溃至(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解决方案:

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

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

这种类型的碰撞可能还有其他原因,所以此解决方案可能不适用,但可能需要检查模型中的属性名称与Predicate Programming Guide中的保留字列表。