Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/119.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ios-核心数据-如果在保存完成之前删除,则应用程序崩溃_Ios_Core Data_Asynchronous_Crash_Nested - Fatal编程技术网

ios-核心数据-如果在保存完成之前删除,则应用程序崩溃

ios-核心数据-如果在保存完成之前删除,则应用程序崩溃,ios,core-data,asynchronous,crash,nested,Ios,Core Data,Asynchronous,Crash,Nested,我的应用程序只需添加一些用户信息(姓名、生日、缩略图等)和核心数据 我注意到,如果我在创建一个用户后立即删除它,我的应用程序就会停止工作(不是崩溃,xCode不会返回崩溃日志,什么都不会) 我正在使用异步嵌套上下文来保存用户信息,因此我猜这种行为是由于执行delete语句之前执行了save语句 但由于我对核心数据完全是初学者,我真的不知道如何处理它。我甚至不知道我是否以正确的方式声明了嵌套上下文 这是我的保存代码: NSManagedObjectContext *tmpContext = [[N

我的应用程序只需添加一些用户信息(姓名、生日、缩略图等)和核心数据

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

我正在使用异步嵌套上下文来保存用户信息,因此我猜这种行为是由于执行
delete
语句之前执行了
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.managedObjectContext
是一种
NSPrivateQueueConcurrencyType
self.backgroundManagedObjectContext
是一种
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]);
    }

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

您的删除可能使用的是由不同上下文创建的
BSStudent
。下面的代码将修复此问题

NSManagedObjectContext * deleteContext = student.managedObjectContext;
[deleteContext deleteObject:student];
如果确实要使用其他上下文,请使用ObjectID重新蚀刻学生

NSManagedObject * studentToDelete = [self.managedObjectContext objectWithID:student.objectID];
[self.managedObjectContext deleteObject:studentToDelete];
嵌套上下文提示 您的上下文可能没有问题,但我看到很多人不必要地抛出performBlock。对于嵌套上下文,QueueConcurrencyType指的是它将在其上执行核心数据操作的线程,而不是创建它的线程。因此,在performBlock中执行类似save on的操作是不必要的,并且可能导致死锁

保存子上下文时,父上下文将自动与更改同步。如果要自动向上保存到下一个更高的父级,我建议为NSManagedObjectContextDidSave注册父级,以通知子级保存。通过让AppDelegate具有用于创建子上下文的工厂方法,可以简化此过程

- (NSManagedObjectContext *)createChildContext
{
    NSManagedObjectContext *tmpContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    tmpContext.parentContext = self.managedObjectContext;
    //Register for NSManagedObjectContextDidSaveNotification
    return tmpContext;
}

您的删除可能使用的是由不同上下文创建的
BSStudent
,而不是您正在使用的上下文。下面的代码将修复此问题

NSManagedObjectContext * deleteContext = student.managedObjectContext;
[deleteContext deleteObject:student];
如果确实要使用其他上下文,请使用ObjectID重新蚀刻学生

NSManagedObject * studentToDelete = [self.managedObjectContext objectWithID:student.objectID];
[self.managedObjectContext deleteObject:studentToDelete];
嵌套上下文提示 您的上下文可能没有问题,但我看到很多人不必要地抛出performBlock。对于嵌套上下文,QueueConcurrencyType指的是它将在其上执行核心数据操作的线程,而不是创建它的线程。因此,在performBlock中执行类似save on的操作是不必要的,并且可能导致死锁

保存子上下文时,父上下文将自动与更改同步。如果要自动向上保存到下一个更高的父级,我建议为NSManagedObjectContextDidSave注册父级,以通知子级保存。通过让AppDelegate具有用于创建子上下文的工厂方法,可以简化此过程

- (NSManagedObjectContext *)createChildContext
{
    NSManagedObjectContext *tmpContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    tmpContext.parentContext = self.managedObjectContext;
    //Register for NSManagedObjectContextDidSaveNotification
    return tmpContext;
}

如果将删除内容包装在
performBlock
调用中,则无法在保存
performBlock
的同时执行

e、 g:

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


我假设您是因为objectID在保存完成之前变得无效或更改而导致崩溃的,在调用堆栈顶部附近,您会看到关于“hash64”之类的内容,如果您将删除内容包装在
performBlock
调用中,则它不能与保存
performBlock
同时执行

e、 g:

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


我假设发生崩溃是因为objectID在保存完成之前变得无效或正在更改,在调用堆栈顶部附近,您将看到一些关于“hash64”之类的内容

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