【问题标题】:ios - Core data - app crash if deleting before save finishedios - 核心数据 - 如果在保存完成之前删除应用程序崩溃
【发布时间】:2013-01-27 00:28:31
【问题描述】:

我的应用只是使用 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.managedObjectContextNSPrivateQueueConcurrencyTypeself.backgroundManagedObjectContextNSMainQueueConcurrencyType。而self.backgroundManagedObjectself.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]);
    }

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

【问题讨论】:

    标签: ios core-data asynchronous crash nested


    【解决方案1】:

    您的删除可能使用了由与您删除时不同的上下文创建的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;
    }
    

    【讨论】:

    • 仍然不能使用`NSManagedObjectContext * deleteContext = student.managedObjectContext;。为了精确起见,如果我在保存后等待几秒钟,删除就会起作用。仅当我在创建用户后立即删除用户时,它才会崩溃。关于您的“嵌套上下文提示”,我仍然不完全了解它是如何工作的。你能提供我正确的方法来编写我的保存操作吗?
    • 当应用无异常、日志等崩溃时,通常是线程问题。托管对象上下文不是线程安全的。因此,您可能在与创建它的线程不同的线程上使用上下文。
    【解决方案2】:

    如果您将删除包装在 performBlock 调用中,则它不能与保存 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”等的内容

    【讨论】:

      猜你喜欢
      • 2017-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多