在核心数据删除期间找到NSManagedObject以解决一对一关系的问题

时间:2013-01-02 20:39:17

标签: objective-c cocoa cocoa-touch core-data

更新:下面的Martin R提供了一个非常清晰(简洁!)的答案,差不多回答了我的问题。我想我应该改写一下:

你能想到为什么在调用prepareForDeletion时获取连接到另一个NSManagedObject的NSManagedObjects不起作用的任何原因,假设这些对象与被删除的对象一对一连接?

我需要能够调用prepareForDeletion以便我可以在决定是否删除对象的子项之前运行一些实体检查。


当核心数据是一对一的关系时,是否有任何删除对象的子对象的技巧?

我有一个相当复杂的Core Data模型,其中删除单个N​​SManagedObject也应该通过prepareForDeletion删除其子NSManagedObjects。在删除之前立即运行一系列调试NSLog语句,可以发现所有关系都已正确设置。但是,当实际尝试删除对象时,似乎许多(尽管不是全部)这些关系已经丢失,因为尝试通过NSFetchRequest获取一些(但同样不是全部)这些对象会返回空数组。

我似乎无法弄清楚如何获取找到的对象与未找到的对象之间的差异,除了那些找到的是与多个关系相反的,而那些无法找到的对象是一对一的关系: - /

要删除“主”对象,我只需调用[managedObjectContext deleteObject:mainObject];,在主对象的私有API中,我已覆盖prepareForDeletion,如下所示:

- (void)prepareForDeletion
{
//    [super prepareForDeletion]; // commented but uncommenting doesn't change results
    [MyDataManager deleteChildOneForMainObject:self];
    [MyDataManager deleteChildrenTwoForMainObject:self];
    [MyDataManager deleteChildrenThreeForMainObject:self];
}

其中MyDataManager是仅包含类方法的自定义NSObject。然后,MyDataManager通过类似于以下内容的东西在托管对象上下文中搜索相应的NSManagedObject:

- (BOOL)deleteChildOneForMainObject:(MainObject *)mainObject
{
    NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"ChildOne" inManagedObjectContext:managedObjectContext];
    [fetch setEntity:entity];
    [fetch setPredicate:[NSPredicate predicateWithFormat:@"(mainObject == %@)", mainObject]];
    NSError *error;
    NSArray *childOnesToDelete = [managedObjectContext executeFetchRequest:fetch error:&error];
    if (childOnesToDelete.count > 1)
    {
        NSLog(@"[WARNING] More than one ChildOne for mainObject found; deleting all");
    }
    NSLog(@"[TEST] Deleting %i ChildOnes", childOnesToDelete.count);
    for (ChildOne *childOne in childOnesToDelete)
    {
        [managedObjectContext deleteObject:childOne];
    }
    if ([managedObjectContext save:&error]) return YES;
    else NSLog(@"[WARNING] Save error for function [deleteChildOneForMainObject:]");
    return NO;
}

同样,“MainObject”类型的每个NSManagedObject与“ChildOne”具有一对一的关系,与“ChildTwo”和“ChildThree”具有一对多的关系。 “Child One”,“ChildTwo”和“ChildThree”都与“MainObject”有一对一的关系。

2 个答案:

答案 0 :(得分:1)

如果正确设置关系的“删除规则”,Core Data可以自动处理删除“依赖”对象。在这种情况下,您可以设置

  • 删除从 MainObject ChildX 到“Cascade”的关系规则,
  • 删除从 ChildX MainObject 到“Nullify”的反向关系规则。

这意味着

  • 如果删除了 MainObject ,则相关的 ChildX 对象也会被删除。
  • 如果删除 ChildX 对象,则相关 MainObject 的关系值将设置为NULL。

答案 1 :(得分:1)

所以我终于让IRC为我工作了! #iphonedev频道上有帮助的人提供了以下见解:

•(就像Martin R所说的那样)我应该建立可视化界面来构建我的核心数据模型,并使用提供的“删除规则”下拉菜单来创建我的删除逻辑。 (在“实用工具”右侧窗格中,第三个选项卡看起来像一块奶酪。)“Cascade”和“Nullify”是最有用的值。

•“删除规则”对于每种关系都是单向且唯一的,因此您具有相当程度的控制权。

•只需使用该属性,而不是获取与提供的NSManagedObject具有一对一关系的NSManagedObject。使用fetch作为“保护”机制是愚蠢和不必要的,因为根据定义这种关系是一对一的。因此,如果我有YingYang个对象,我应该执行[managedObjectContext deleteObject:ying.yang][managedObjectContext deleteObject:yang.ying]

根据Martin R的回答,最终prepareForDeletion仅与级联删除有关。