核心数据:使用 To many 关系插入和删除

Posted

技术标签:

【中文标题】核心数据:使用 To many 关系插入和删除【英文标题】:Core data: Insert and delete with To many relationship 【发布时间】:2014-02-12 15:27:02 【问题描述】:

我正在使用核心数据制作一个简单的日记应用。

主模型(期刊)将包含标题和正文。 每个条目可以有一个或多个标签。

要插入一个新的(期刊),我只是这样做:

Journal *newJournal  [NSEntityDescription insertNewObjectForEntityForName:@"Journal"
                                             inManagedObjectContext:context];
//Save 

问题一:给条目添加标签的正确方法是什么?

我可以这样做:

Tag *tag1 = [NSEntityDescription insertNewObjectForEntityForName:@"Tag"
                                             inManagedObjectContext:context];
Tag *tag2 = [NSEntityDescription insertNewObjectForEntityForName:@"Tag"
                                             inManagedObjectContext:context];
newJournalEntry.tags = [[NSOrderedSet alloc] initWithObjects:tag1,tag2,nil];
// Save card... 

... 但这将为每个条目创建新标签。我只需要核心数据模型中每个标签的唯一实例。

问题2:如何按标签查询日记条目,例如“获取所有具有fun标签的日记条目”

我还需要获取所有创建的标签并显示它们,例如:“你有 3 个标签:Fun、sport、vacation”

【问题讨论】:

一次提出 1 个问题。为什么你们的关系不是多对多的?您是否生成了托管对象子类(它们有哪些方法)?您是否尝试过运行任何获取请求? 【参考方案1】:

首先,您需要在 Journal 和 Tag 模型之间建立多对多关系,否则您将无法将同一个 Tag 分配给多个 Journal 条目

答案 1: 在将任何标签分配给日记条目之前,从商店中获取现有标签:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Tag"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"name IN %@", @[@"tag1", @"tag2"]];
NSArray *tags = [moc executeFetchRequest:fetchRequest error:&error];

那么您应该只为缺少的标签创建带有-insertNewObjectForEntityName 的标签。

答案 2:

NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Journal"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"tags CONTAINS[cd] %@", @"fun"];
NSArray *journalEntries = [moc executeFetchRequest:fetchRequest error:&error];

您可以在Predicates Programming Guide 中阅读有关谓词的更多信息

【讨论】:

【参考方案2】:

答案 1: 您需要在标签和 journalEntry 之间将模型更改为多对多,然后您需要查询模型以查看标签是否已存在。如果他们这样做,那么您只需将它们链接到您的条目实体。

示例(在伪代码中):

NSOrderedSet tags = nil;
//Create and fetch for the tags you are looking for. Then:

 if([[FetchedResultController fetchedObjects] count] > 0) 

     tags = [[NSOrderedSet alloc] initWithArray:[FetchedResultController fetchedObjects]];

  else 
   //The code you actually have (almost)
   Tag *tag1 = [NSEntityDescription insertNewObjectForEntityForName:@"Tag"
                                         inManagedObjectContext:context];
   Tag *tag2 = [NSEntityDescription insertNewObjectForEntityForName:@"Tag"
                                         inManagedObjectContext:context];
   tags = [[NSOrderedSet alloc] initWithObjects:tag1,tag2,nil];
 

 //Then just set your tags
 newJournalEntry.tags = tags;

答案 2: 一旦你实现了答案一,然后你寻找那些标签,然后只使用与应该是 NSSet 的 journalEntry 的关系(例如:tags.journal)。

再次伪代码:

for(Tag *tag in [FetchResultController fetchedObjects]) 

       //Get the Journal Entries using:  "tag.journal" 
      NSSet *journalEntriesWithTagRequested = tag.journal;

      // Do what you must with journalEntriesWithTagRequested . . .

   

【讨论】:

以上是关于核心数据:使用 To many 关系插入和删除的主要内容,如果未能解决你的问题,请参考以下文章

NSPredicate:与日期iOS的to-Many关系

核心数据和多对多

核心数据,关系消失

NSPredicate 按属性过滤核心数据关系 NSSet

有序核心数据关系 - 如何管理或默认排序是什么?

核心数据:与状态的多对多关系