非法尝试在不同上下文中的对象之间建立关系“清单”

Posted

技术标签:

【中文标题】非法尝试在不同上下文中的对象之间建立关系“清单”【英文标题】:Illegal attempt to establish a relationship 'checklists' between objects in different contexts 【发布时间】:2013-08-09 14:21:20 【问题描述】:

我正在使用 Core Data 离线存储我的 ios 应用程序,但我不断收到以下错误:

问题是,我肯定使用相同的上下文来创建关系。以下是触发问题的代码块:

 NSMutableSet *checklists = [[NSMutableSet alloc] init];
for (NSDictionary *dict in array)
    Checklists *checklist = [self addChecklist:dict withContext:context];
    [checklists addObject:checklist];
    DLog(@"context: %@", checklist.managedObjectContext);


//Delete any lists that aren't from the server
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
Users *currentUser = (Users *)[self getUserWithId:[defaults objectForKey:@"user_id"] withContext:context];
DLog(@"context: %@", context);
currentUser.checklists = checklists;

在最后一行currentUser.checklists = checklists 抛出异常。来自context 的日志是相同的,并且对象在同一个线程中。有没有人遇到过这种情况?

addChecklist:withContext: 的代码:

- (Checklists *) addChecklist:(NSDictionary *) dict withContext:(NSManagedObjectContext *)context
    //Pull the list from the database and update
    Checklists *checklist = [self getChecklistWithId:dict[@"_id"] withContext:context];

    //If the list doesn't exist, add it to the database
    if(!checklist)
        checklist = (Checklists *)[NSEntityDescription insertNewObjectForEntityForName:@"Checklists" inManagedObjectContext:context];

    //Update or create the list attributes
    checklist.checklist_id = dict[@"_id"] ? dict[@"_id"] : [NSString stringWithFormat:@"%d", (arc4random() % 2000)];
    checklist.desc = dict[@"description"] == [NSNull null] ? nil : dict[@"description"];
    checklist.name = dict[@"name"] == [NSNull null] ? nil : dict[@"name"];
    checklist.published = dict[@"published"] == [NSNull null] ? 0 : dict[@"published"];
    checklist.created_at = dict[@"created_at"] == [NSNull null] ? nil : dict[@"created_at"];
    checklist.updated_at = dict[@"updated_at"] == [NSNull null] ? nil : dict[@"updated_at"];

    [self addChecklistSections:dict[@"checklist_sections"] withChecklist:checklist withContext:context];

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    [self saveMasterContext];

    return checklist;

getUserWithId: withContext: 的代码

- (Users *) getUserWithId:(NSString *)user_id withContext:(NSManagedObjectContext *) context

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Users" inManagedObjectContext:context];
    [request setEntity:entity];
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"(user_id = %@)", user_id];
    [request setPredicate:pred];

    NSError *error = nil;
    NSMutableArray *users = [[context executeFetchRequest:request error:&error] mutableCopy];
    if (users == nil || users.count == 0) 
        return nil;
    
    return users[0];

【问题讨论】:

你应该发布addChecklistgetUserWithId的内容。您的错误是通过使用两个 MOC 创建两个不同的实体然后在它们之间创建关系来触发的。因此,请确保您对 ChecklistUsers 实体使用相同的 NSManagedObjectContext。 @danypata 我刚刚添加了您要求的代码 @danypata 用户绝对不是零 - 我刚刚打印出来 考虑同时记录 [checklist managedObjectContext][user managedObjectContext] 而不是 context,只是为了排除 context 正在以某种方式被更改以使其看起来像你已经把事情放在正确的可能性记录它们时的上下文。另外,也许查看saveMasterContext 的代码并验证它没有以某种方式篡改context @CarlVeazey 我通过按照您的建议打印出 managedObjectContexts 来验证它们是相同的上下文。 【参考方案1】:

我看不出为您获取的用户创建mutableCopy 的动机。我认为这可能是您收到上下文错误的原因。从理论上讲,它应该只是复制指向您的对象的指针,但谁知道幕后发生了什么。

相反,将获取请求的 fetchLimit 设置为 1 并检查您是否只得到一个结果。直接返回此结果,而不是其副本。

也不清楚为什么在传递上下文时调用上下文保存方法 (saveMasterContext)。调用会更合乎逻辑

[context save:nil];

此外,按照 Apple 丰富的示例代码,您应该考虑将上下文设为类的 @property,而不是将其作为方法参数传递。

--

顺便说一句,我真的认为您应该放弃以复数形式命名实体的习惯。清单实际上是清单,而不是清单。

另外,依赖字符串的 id 方案效率不高。考虑使用数字等价物。此外,我发现分配一个随机清单 ID 相当冒险。

此外,您的代码中有一些杂散行,例如在从 addChecklist 返回之前为用户默认值定义一个未使用的变量。

【讨论】:

以上是关于非法尝试在不同上下文中的对象之间建立关系“清单”的主要内容,如果未能解决你的问题,请参考以下文章

为啥我会得到:非法尝试在不同上下文中的对象之间建立关系...

NSInvalidArgumentException:非法尝试在不同上下文中的对象之间建立关系

单一上下文但“非法尝试在不同上下文中的对象之间建立关系‘xyz’

为啥我的产品->存档因“非法尝试在不同上下文中的对象之间建立关系”压缩类型“而失败?

核心数据:非法尝试建立关系+(空)上下文

为啥在一个视图中有不同的上下文?