【问题标题】:Auto-Incremented Object ID in Core Data?核心数据中的自动递增对象 ID?
【发布时间】:2011-09-16 15:07:24
【问题描述】:

我正在使用具有多个关系的多个 NSManagedObject 类型。如何让 Core Data 自动为我填充对象 ID?我正在寻找类似 SQL 中的索引键之类的东西,因此不允许给定对象的两个实例具有相同的 ID。

编辑:

我希望我的所有“帐户”对象都有唯一的 ID。我只是在 `countForFetchRequest 中添加一个,但我意识到当删除倒数第二个对象然后添加一个时,最后两个对象现在具有相同的 ID。

如何确保给定值对于我的“帐户”NSManagedObject 的所有实例都具有唯一值?

EDIT2:

我需要一个单独的 ID 用于排序。

【问题讨论】:

    标签: iphone core-data xcode4


    【解决方案1】:

    我已经为上述问题提出了这个解决方案,希望它对某些人有所帮助。

    AppDelegate *appdelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
    
    NSManagedObjectContext *context = [appdelegate managedObjectContext];
    
    NSError *error = nil;
    
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    
    NSEntityDescription *chatHist = [NSEntityDescription
                                         entityForName:@"ChatHistory" inManagedObjectContext:context];
    [fetchRequest setEntity:chatHist];
    
    int chatIdNumber = 0;
    
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
    if ([fetchedObjects count] > 0) {
        ChatHistory *chatHistObj = [fetchedObjects objectAtIndex:[fetchedObjects count]-1];
        chatIdNumber = [chatHistObj.chatId intValue];
    }
    
    chatIdNumber = chatIdNumber+1;
    ChatHistory *chat_History  = [NSEntityDescription          insertNewObjectForEntityForName:@"ChatHistory" inManagedObjectContext:context];
    
    chat_History.chatId = [NSString stringWithFormat:@"%d",chatIdNumber];
    

    【讨论】:

      【解决方案2】:

      根据您的 EDIT2 和 Edit3,以下答案将对您有所帮助。假设您的 id 字段为 NSNumber,ID 为 unsignedInt。

      1) 获取对应实体的所有记录。

      NSError *error = nil;
      NSArray *array = [self fetchAllFileEntity:&error];
      

      2) 找出属于该结果的最大数。

      NSNumber *maxValue = nil;
      if (array)
          maxValue = [array valueForKeyPath:@"@max.uniqueId.unsignedIntegerValue"];
      else
          maxValue = [NSNumber numberWithUnsignedInteger:0];
      

      3) 将 maxValue+1 分配给您的新实体

      entity.uniqueId = [NSNumber numberWithUnsignedInteger:maxValue.unsignedIntegerValue+1];
      

      【讨论】:

      • 当我删除一些行(具有最大值的行)时会发生什么
      • 用 ex 解释:假设如果你有 5 行的意思,@max 计数是 5。现在你要删除第 5 行的意思,最大计数是 4。所以当你尝试添加新的,自动将 5 分配给新的,即表中存在的所有行都应具有唯一值(本地 db)。
      • 我也面临同样的问题,谁能提供适当的解决方案。
      【解决方案3】:

      我解决这个问题的方法是使用 Core Data 聚合。我实际上最终自己分配了 ID。

      基本上,我在 Core Data 中查询我的实体的所有实体 ID,然后遍历它们。如果我发现一个高于当前临时 ID 的 ID,我将临时 ID 设置为高于聚合 ID。完成后,我会自动拥有一个高于列表中最高 ID 的 ID。我看到的唯一缺陷是是否缺少 ID。 (我相信也有一个简单的解决方法。)

      //
      //  Create a new entity description
      //
      
      NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:self.managedObjectContext];
      
      //
      //  Set the fetch request
      //
      
      NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
      [fetchRequest setEntity:entity];
      
      //
      //  We need to figure out how many 
      //  existing groups there are so that 
      //  we can set the proper ID.
      //
      //  To do so, we use an aggregated request.
      //
      
      [fetchRequest setResultType:NSDictionaryResultType];
      [fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:@"entityID"]];
      
      NSError *error = nil;
      
      NSArray *existingIDs = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
      
      
      if (error != nil) {
      
          //
          //  TODO: Handle error.
          //
      
          NSLog(@"Error: %@", [error localizedDescription]);
      }
      
      NSInteger newID = 0;
      
      for (NSDictionary *dict in existingIDs) {
          NSInteger IDToCompare = [[dict valueForKey:@"entityID"] integerValue];
      
          if (IDToCompare >= newID) {
              newID = IDToCompare + 1;
          }
      } 
      
      //
      //  Create the actual entity
      //
      
      MyEntity *newEntity = [[MyEntity alloc] initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];
      
      //
      //  Set the ID of the new entity
      //
      
      [newEntity setEntityID:[NSNumber numberWithInteger:newID]];
      
      //
      //   ... More Code ...
      //
      

      【讨论】:

      • 您不需要获取所有行 - 只需最后使用 id 谓词降序排序
      • 如果使用神奇的记录 entity.entityID = @([[Entity findFirstOrderedByAttribute:@"entityID" descending:NO] entityID].intValue+1);
      【解决方案4】:

      所有NSManagedObjects 都会自动拥有一个唯一的NSManagedObjectID。没有自定义自动递增属性的概念,但自己编写一个当然很容易。

      【讨论】:

      • 我可以使用 NSManagedObjectID 从 Core Data 存储中获取特定项目吗?
      • 我实际上最终使用聚合编写了自己的自动增量。如果你愿意,请看我的回答。为你 +1。
      • “简单”不是我会使用的词。 “痛苦”更贴切。可以理解,这不是 Core Data 的工作。但是还是……
      猜你喜欢
      • 2016-04-11
      • 1970-01-01
      • 2013-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-17
      • 1970-01-01
      相关资源
      最近更新 更多