【问题标题】:Core Data (Mac) How to implement auto increment on an ID fieldCore Data (Mac) 如何在 ID 字段上实现自动递增
【发布时间】:2011-06-11 12:24:33
【问题描述】:

我想知道是否有人可以指出如何在 coredata 实体中的属性上设置自动增量。我知道索引复选框只是使字段索引以提高搜索和查找速度。

我也知道我必须在代码中执行此操作,但我不确定如何获取最后/最高 ID 来设置新对象 ID。几年前我找到了如何做到这一点,但再也找不到了。

我对 Objective-C 的了解非常有限,对 coredata 更是如此。此外,如果有人可以建议如何确保一个字段是唯一的,例如名称字段,那就太好了。

我的代码是here,如果你想看看我到目前为止做了什么。该项目是一个基本数据库,其中包含零件和位置以及工具。它只是部分完成,基本上是我个人电子套件的一个小型数据库。我敢肯定有一些应用程序可以做到这一点,但当你自己做时它总是会更好

【问题讨论】:

  • 我在想什么,我有一个实体类,所以如果单击新按钮时我的代码从位置表中获取最高 id 并将该值放在 id 字段中表。
  • 您需要一个自动递增的 id 字段来做什么?在 CoreData 中通常没有必要。如果您需要唯一标识符,请使用 objectID 属性。如果您需要关系,请在 CoreData 中明确设置。

标签: objective-c xcode core-data auto-increment


【解决方案1】:

我不太确定 id 在您的应用程序中的作用,但我的第一个观察是您的数据模型中的所有实体都有名称和 id,因此它们可能应该包含一个抽象的超实体姓名和身份证。除此之外,您可以像这样检索集合中的最大 id:

Category *cat = /* get a category  */;
NSSet *parts = cat.parts;
NSNumber *maxID = [parts valueForKeyPath:@"@max.id"];

对于某个类别的 id,您可以对所有类别执行获取请求,然后在返回的数组上使用此技术。我不知道您是否希望每个模型对象的 id 保持唯一,或者对于添加到每个实体的第一个对象,您希望 id 以 0 开头。

要确保字段是唯一的,您可以使用托管对象验证。这在核心数据编程指南中有描述,在模型对象实现指南中有更详细的描述。确保名称是唯一的需要您针对 validateName:error: 方法中的所有名称对其进行测试。制作一个抽象的超级实体将使这变得容易得多。为此,您需要获取抽象超级实体中的所有对象名称,并根据要验证的值对它们进行测试。

编辑:如果您使用抽象超级实体,那么如果您希望它们是唯一的,那么您应该获取抽象超级实体中对象的最大 ID。同样正如其他人指出的那样,托管对象的 objectID 是它的唯一标识符,它始终是相同的,但是查看应用程序,我认为这并不是您真正想要的,因为它们将是计算机编号而不是创建新对象时增加已知的最高 id 的更友好的结果。另一件事是,您应该在 awakeFromInsert 中设置对象 ID,以便仅在创建对象时调用它。

【讨论】:

  • ID 字段是我将在现实生活中用于零件箱的编号,这就是为什么我希望它是唯一的并成为集合中的下一个编号。我会照你说的做,获取所有类别并找到集合中最大的。我确信我可以在查询中使用类似 max() 的东西。我将阅读获取请求
  • 使用 fetch 请求,您可以使用排序描述符获取最高 id,然后在结果数组上调用 lastObject。
  • 一个问题,如果我使用 - (void) awakeFromInsert 方法,我会在表中得到两个。阻止这种情况的唯一方法是注释掉整个方法。你知道为什么我在方法中设置了一个断点,只在按下新按钮时调用一次。
  • 当您调用 insertNewObjectForEntityForName:inManagedObjectContext: 时,会创建一个空白托管对象,然后调用 awakeFromInsert:。我不知道为什么它会插入两次,除非你在 awakeFromInsert 中创建一个新的托管对象。我对 NSArrayController 了解不多,因为我是一名 iOS 开发人员,但您可能需要设置 entityName。多看一下应用程序包,在 add 方法中设置 id 可能比在 awakeFromInsert 中设置更好。另外我不确定您在哪里设置阵列控制器中的内容。
  • 应用程序启动时不会将存储的对象添加到排列的对象中,并且托管对象上下文永远不会保存,因此您所做的任何事情都会在您关闭后消失。更重要的是,当您添加新组件时,它们看起来像这样: ToolBox[15300:a0f] 已插入: (entity: Part; id: 0x10017aa00 ; data: { Current = 1; Name = nil; Note = nil; Picture = nil; Quantity = 0; category = nil; id = 0; location = nil; Specification = ( ); }) 注意没有类别。
【解决方案2】:

这是苹果实现自动增量的方式:

 - (void) awakeFromInsert
     {
    [super awakeFromInsert];
    static int tempID = 0;
    [self setValue:[NSNumber numberWithInt:++tempID] forKey:@"id"];
}

【讨论】:

  • 不要使用这个!原始 Apple 示例代码包含一个注释,上面的 sn-p 仅用于说明目的,不应在生产代码中使用。每次启动应用时,它都会将自动增量值重置为 0。
  • 但是话又说回来,有一个额外的 dispatch_once 来实际获取当前实体的最大“id”是可行的;只要所有插入都确定不是并发的
猜你喜欢
  • 2020-12-29
  • 2012-05-12
  • 2012-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-20
  • 2012-01-09
相关资源
最近更新 更多