0

我的应用程序只是使用 Core Data 添加了一些用户信息(姓名、生日、缩略图……)。

我注意到,如果我在创建用户后立即删除它,我的应用程序就会停止工作(不是崩溃,xCode 不返回崩溃日志,什么也没有)。

delete我正在使用异步嵌套上下文来保存我的用户信息,所以我猜这种行为是由于我的语句在我的语句之前执行的事实save

但由于我是 Core Data 的初学者,我真的不知道如何处理它。我什至不知道我是否以正确的方式声明了嵌套上下文。

这是我的save代码:

NSManagedObjectContext *tmpContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    tmpContext.parentContext = self.backgroundManagedObjectContext;

    BSStudent *newStudent = (BSStudent *)[NSEntityDescription insertNewObjectForEntityForName:kBSStudent inManagedObjectContext:tmpContext];

    newStudent.firstname = firstname;
    newStudent.lastname = lastname;
    newStudent.birthdate = birthdate;
    newStudent.thumbnail = thumbnail;
    newStudent.createdAt = [NSDate date];

    [self dismissViewControllerAnimated:YES completion:nil];

    [tmpContext performBlock:^{
        [tmpContext save:nil];

        [self.backgroundManagedObjectContext performBlock:^{
            NSError *error;
            if (![self.backgroundManagedObjectContext save:&error]) {
                NSLog(@"%@", [error localizedDescription]);
            }

            [self.managedObjectContext performBlock:^{
                NSError *error;
                if (![self.managedObjectContext save:&error]) {
                    NSLog(@"%@", [error localizedDescription]);
                }
            }];
        }];
    }];

为了精确,self.managedObjectContextis aNSPrivateQueueConcurrencyTypeself.backgroundManagedObjectContextis a NSMainQueueConcurrencyType。并且self.backgroundManagedObject是 的孩子self.managedObjectContext

这是我的删除代码:

    BSStudent *student = objc_getAssociatedObject(alertView, kDeleteStudentAlertAssociatedKey);

    // on supprimer l'objet et on sauvegarde le contexte
    [self.managedObjectContext deleteObject:student];
    NSError *error;
    if(![self.managedObjectContext save:&error]) {
        NSLog(@"%@", [error localizedDescription]);
    }

有人可以知道如何正确处理这种情况吗?

4

2 回答 2

4

您的删除可能使用BSStudent由与您删除时不同的上下文创建的。下面的代码将解决这个问题。

NSManagedObjectContext * deleteContext = student.managedObjectContext;
[deleteContext deleteObject:student];

如果您真的想使用其他上下文,请使用 ObjectID 重新获取学生

NSManagedObject * studentToDelete = [self.managedObjectContext objectWithID:student.objectID];
[self.managedObjectContext deleteObject:studentToDelete];

嵌套上下文提示

您的上下文可能没问题,但我看到很多人不必要地到处乱扔 performBlock。对于嵌套上下文,QueueConcurrencyType 指的是它将在其上执行 Core Data 操作的线程,而不是创建它的线程。因此,在它的 performBlock 中执行诸如 save 之类的操作是不必要的,并且可能导致死锁。

当您保存子上下文时,父上下文会自动与更改同步。如果您想自动向上保存到下一个更高的父级,我建议为子级保存的 NSManagedObjectContextDidSaveNotification 注册父级。您可以通过让 AppDelegate 具有用于创建子上下文的工厂方法来简化此操作。

- (NSManagedObjectContext *)createChildContext
{
    NSManagedObjectContext *tmpContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    tmpContext.parentContext = self.managedObjectContext;
    //Register for NSManagedObjectContextDidSaveNotification
    return tmpContext;
}
于 2013-01-27T01:22:11.353 回答
1

如果您将 delete 包装在performBlock调用中,则它不能与 save 同时执行performBlock

例如:

BSStudent *student = objc_getAssociatedObject(alertView, kDeleteStudentAlertAssociatedKey);

// on supprimer l'objet et on sauvegarde le contexte
[self.managedObjectContext performBlock:^{
    [self.managedObjectContext deleteObject:student];
    NSError *error;
    if(![self.managedObjectContext save:&error]) {
        NSLog(@"%@", [error localizedDescription]);
    }
}];

这是处理上下文的“首选”方式,因为它序列化对上下文的访问并将所有这些操作保留在上下文线程上,

我假设您正在崩溃,因为 objectID 在保存完成之前变得无效或更改,在调用堆栈的顶部附近您会看到有关“hash64”等的内容

于 2013-01-27T12:50:29.800 回答