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