处理在多对多关系中删除Core Data对象

时间:2013-02-18 20:46:06

标签: iphone ios core-data

使用核心数据,我正在寻找一个具有以下多对多关系的标记系统:

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

在这种情况下,article可以有多个tags,同一个tags可以分配给多个articles。每当编辑article个标签时,我会删除与tags相关联的所有先前article,并重新添加仍然相关的标签,如下所示:

// 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];
    }
}

我的问题是如何最好地处理与这两种关系相关的删除规则。基本上我正在寻找的行为是当我从tag中删除article时,如果没有其他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!");
    }
}

为了完整性,这是一个示例输出(显示两个articles的创建,其中包含两个共享的tags:食物和快餐。在删除一个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)

2 个答案:

答案 0 :(得分:4)

我发现此问题的最佳解决方案是将删除规则设置为Nullify,并在article的{​​{1}} NSManagedObject方法中处理删除:

prepareForDeletion

答案 1 :(得分:0)

除删除规则外一切正常。使用此配置,CoreData不会保存带有错误的上下文:

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

要完成此任务,您应该将tag.articles关系设置为Nullify,并将我的articles.tags关系设置为Cascade。这将按预期工作。

第二。您的代码崩溃,但异常:集合&lt; _NSFaultingMutableSet:0x841de10&gt;在被枚举时被突变。制作关系副本以安全地枚举它:

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