在核心数据中进行批量删除时尝试实现主子托管对象上下文
Trying to implement master-child Managed Object Context when doing mass delete in Core Data
我正在做一个项目,我正在大量删除从核心数据中检索到的许多 NSManagedObjects (MO)。当我遍历这个 MO 集合时,我还通过在初始 MO 集合的迭代期间调用获取方法来检索其他 MO。
如果在此迭代过程中,从获取请求中找到对象,则删除 MO。我意识到这是一个糟糕的架构设计,因为这些 MO 实际上应该彼此具有相反的关系,因此通过级联删除规则,所有这些对象都可以轻松删除。不幸的是,情况并非如此,回过头来进行这些修复太难了,这就是我来这里的原因。
此外,我意识到我正在描述的这个场景应该使用父子 NSManagedObjectContext 来做正确的事情,当然,以避免发生崩溃。鉴于我正在使用的架构,我不确定如何实现这一点。这是我正在使用的代码示例:
- (void)massDelete {
...
NSArray *objectsToPurge = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (objectsToPurge) {
[objectsToPurge enumerateObjectsUsingBlock:^(MyMO *mo, NSUInteger idx, BOOL *stop) {
OtherMO *otherMO = [self fetchOtherMO:mo];
if (otherMO) {
[self.managedObjectContext deleteObject:otherMO];
}
[self.managedObjectContext deleteObject:mo];
}];
}
[self.managedObjectContext save:&purgeError];
}
- (OtherMO *)fetchOtherMO:(MyMO *)mo {
NSManagedObjectContext *context = [[MySingleton sharedInstance] managedObjectContext];
NSError *error;
// Create fetch request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"OtherMO" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
// Create predicate
NSPredicate *pred = [NSPredicate predicateWithFormat:@"myMO == %@", mo];
[fetchRequest setPredicate:pred];
NSArray *items = [context executeFetchRequest:fetchRequest error:&error];
if ([items count]>0) {
return [items firstObject];
} else {
return nil;
}
}
就像我说的,我意识到我在这里使用了两个单独的 NSManagedObjectContext,我需要实现一个父子结构,但我不确定如何做到这一点。鉴于我无法对核心数据架构做任何事情,并且这是我正在处理的场景,什么是解决我的问题的最佳解决方案?
我觉得不需要两个MOC,一个就可以解决。只需将它作为参数传递给 fetchOtherMOByMyMo:(MyMo *)mo onContext:(NSManagedObjectContext *)context.
而且你忘了使用 performBlock:
检查一下,它应该可以正常工作而不会崩溃:
- (void)massDelete {
...
__weak typeof(self) weakSelf = self;
self.managedObjectContext performBlock:^{
NSArray *objectsToPurge = [weakself.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (objectsToPurge) {
[objectsToPurge enumerateObjectsUsingBlock:^(MyMO *mo, NSUInteger idx, BOOL *stop) {
OtherMO *otherMO = [weakself fetchOtherMO:mo onContext:weakself.managedObjectContext];
if (otherMO) {
[weakself.managedObjectContext deleteObject:otherMO];
}
[weakself.managedObjectContext deleteObject:mo];
}];
}
[weakself.managedObjectContext save:&purgeError];
});
}
- (OtherMO *)fetchOtherMO:(MyMO *)mo onContext:(NSManagedObjectContext *)context{
NSError *error;
// Create fetch request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"OtherMO" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
// Create predicate
NSPredicate *pred = [NSPredicate predicateWithFormat:@"myMO == %@", mo];
[fetchRequest setPredicate:pred];
NSArray *items = [context executeFetchRequest:fetchRequest error:&error];
if ([items count]>0) {
return [items firstObject];
} else {
return nil;
}
}
我正在做一个项目,我正在大量删除从核心数据中检索到的许多 NSManagedObjects (MO)。当我遍历这个 MO 集合时,我还通过在初始 MO 集合的迭代期间调用获取方法来检索其他 MO。
如果在此迭代过程中,从获取请求中找到对象,则删除 MO。我意识到这是一个糟糕的架构设计,因为这些 MO 实际上应该彼此具有相反的关系,因此通过级联删除规则,所有这些对象都可以轻松删除。不幸的是,情况并非如此,回过头来进行这些修复太难了,这就是我来这里的原因。
此外,我意识到我正在描述的这个场景应该使用父子 NSManagedObjectContext 来做正确的事情,当然,以避免发生崩溃。鉴于我正在使用的架构,我不确定如何实现这一点。这是我正在使用的代码示例:
- (void)massDelete {
...
NSArray *objectsToPurge = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (objectsToPurge) {
[objectsToPurge enumerateObjectsUsingBlock:^(MyMO *mo, NSUInteger idx, BOOL *stop) {
OtherMO *otherMO = [self fetchOtherMO:mo];
if (otherMO) {
[self.managedObjectContext deleteObject:otherMO];
}
[self.managedObjectContext deleteObject:mo];
}];
}
[self.managedObjectContext save:&purgeError];
}
- (OtherMO *)fetchOtherMO:(MyMO *)mo {
NSManagedObjectContext *context = [[MySingleton sharedInstance] managedObjectContext];
NSError *error;
// Create fetch request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"OtherMO" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
// Create predicate
NSPredicate *pred = [NSPredicate predicateWithFormat:@"myMO == %@", mo];
[fetchRequest setPredicate:pred];
NSArray *items = [context executeFetchRequest:fetchRequest error:&error];
if ([items count]>0) {
return [items firstObject];
} else {
return nil;
}
}
就像我说的,我意识到我在这里使用了两个单独的 NSManagedObjectContext,我需要实现一个父子结构,但我不确定如何做到这一点。鉴于我无法对核心数据架构做任何事情,并且这是我正在处理的场景,什么是解决我的问题的最佳解决方案?
我觉得不需要两个MOC,一个就可以解决。只需将它作为参数传递给 fetchOtherMOByMyMo:(MyMo *)mo onContext:(NSManagedObjectContext *)context.
而且你忘了使用 performBlock:
检查一下,它应该可以正常工作而不会崩溃:
- (void)massDelete {
...
__weak typeof(self) weakSelf = self;
self.managedObjectContext performBlock:^{
NSArray *objectsToPurge = [weakself.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (objectsToPurge) {
[objectsToPurge enumerateObjectsUsingBlock:^(MyMO *mo, NSUInteger idx, BOOL *stop) {
OtherMO *otherMO = [weakself fetchOtherMO:mo onContext:weakself.managedObjectContext];
if (otherMO) {
[weakself.managedObjectContext deleteObject:otherMO];
}
[weakself.managedObjectContext deleteObject:mo];
}];
}
[weakself.managedObjectContext save:&purgeError];
});
}
- (OtherMO *)fetchOtherMO:(MyMO *)mo onContext:(NSManagedObjectContext *)context{
NSError *error;
// Create fetch request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"OtherMO" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
// Create predicate
NSPredicate *pred = [NSPredicate predicateWithFormat:@"myMO == %@", mo];
[fetchRequest setPredicate:pred];
NSArray *items = [context executeFetchRequest:fetchRequest error:&error];
if ([items count]>0) {
return [items firstObject];
} else {
return nil;
}
}