2013-02-18 56 views
2

使用核心数据,我期待下建立有以下一对多关系的标签系统:处理核心数据的缺失对象的一对多关系

article.tags <<------->> tag.articles 

在这种情况下的article可以有无数tags,并且那些相同的tags可以被分配给多个articles。每当article的标签编辑,我删除与相关联的所有以前tagsarticle并重新添加那些仍然具有现实意义,就像这样:

// Remove any existing tags from this article 
if(article.tags.count) 
{ 
    NSSet *existingEventTags = [article.tags copy]; 
    for (NSManagedObject *tag in existingEventTags) 
    { 
     [[article mutableSetValueForKey:@"tags"] removeObject:tag]; 
     [moc deleteObject:tag]; 
    } 
} 

// Now re-assign any applicable tags to this article 
for(NSString *tag in tags) 
{ 
    Tag *existingTag = [self existingTagWithString:tag]; 
    if(existingTag) 
    { 
     [article addTagsObject:existingTag]; 
    } 
    else 
    { 
     NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Tag" inManagedObjectContext:moc]; 
     Tag *newTag = (Tag *)[[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:moc]; 
     newTag.name = tag; 
     [article addTagsObject:newTag]; 
    } 
} 

我的问题是如何最好地处理与相关删除规则这两个关系。基本上,我要找的行为是当我从article中删除tag时,我只想完全删除它,如果没有其他articles已被标记。

要完成此操作,我已将我的tag.articles关系设置为Nullify,并将我的articles.tags关系设置为Cascade。但是,删除文章时,与其关联的任何标签(无论它们是否与其他文章关联)都将被删除。为了测试这个我写了一个简单的调试功能,我将在下面包括:

- (void)debugTags 
{ 
    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Tag" inManagedObjectContext:moc]; 
    [request setEntity:entity]; 

    // Execute the fetch. 
    NSError *error = nil; 
    NSArray *objects = [moc executeFetchRequest:request error:&error]; 
    if (objects != nil && [objects count] > 0) 
    { 
     NSLog(@"Found %d tags", [objects count]); 
     for(Tag *tag in objects) 
     { 
      NSLog(@"\t%@ (%d events)", tag.name, tag.articles.count); 
     } 
    } 
    else 
    { 
     NSLog(@"No tags found!"); 
    } 
} 

为了完整起见,这里是一个示例输出(显示了两个共享tags两个articles创建:食品和快餐)。下面的一个article删除,我希望仍然寻找食物和快餐店里,但与1

Before deletion 
--------------- 

Found 4 tags 
    breakfast (1 events) 
    food (2 events) 
    fastfood (2 events) 
    lunch (1 events) 

After deletion 
-------------- 

Found 1 tags 
    lunch (1 events) 
+0

这对我来说很好。这些规则是正确的。你做过任何测试,看看它是否有效? – 2013-02-18 22:16:05

回答

4

,我发现这个问题的最佳解决方案是同时设置删除规则废除,并处理在我articleNSManagedObjectprepareForDeletion方法删除:

- (void)prepareForDeletion 
{ 
    [super prepareForDeletion]; 

    for (Tag *tag in self.tags) 
    { 
     if(tag.events.count == 1) 
     { 
      [self.managedObjectContext deleteObject:tag]; 
     } 
    } 
} 
+0

不错!我不知道这种方法。感谢分享 ! :) – Lapinou 2016-12-20 08:24:46

0

一切关系计数除了删除规则是正确的。利用这种配置CoreData不惯于节省方面出现错误:

NSValidationErrorKey=events, NSLocalizedDescription=The operation couldn’t be completed. (Cocoa error 1600.), NSValidationErrorValue=Relationship 'articles' on managed object 

要做到这一点,你应该设置tag.articles关系来抵消,而我articles.tags关系级联。这将按预期工作。

第二。您的代码崩溃,例外:收集< _NSFaultingMutableSet:0x841de10>在枚举时发生了变化。做关系的副本安全地通过它列举:

NSSet* tags = [[object valueForKey:@"tags"] copy]; 
    for (NSManagedObject *tag in tags) { 
     [[object mutableSetValueForKey:@"tags"] removeObject:tag]; 
     [context deleteObject:tag]; 
    } 
+0

好的。原始文章包含我自更新以来未经测试的伪代码。不幸的是,你所建议的删除规则并不像我预期的那样工作。我再次更新了原始问题以更好地解释问题。 – ndg 2013-02-19 18:34:57