Ios 在后台线程上保存coredata会导致获取陷入死锁和崩溃
我将coredata保存在后台方法(父-子)中,但获取是在主线程上完成的。所以我在fetch方法中遇到了死锁,有时应用程序会崩溃。我做错什么了吗?如何在不影响主线程的情况下改进save和fetch?我读过很多文档,但没有一个文档解释我如何在项目中使用这两种方法。如果这是一个错误的问题,请引导我找到正确的解决方案,并让我知道我的错误Ios 在后台线程上保存coredata会导致获取陷入死锁和崩溃,ios,objective-c,multithreading,core-data,Ios,Objective C,Multithreading,Core Data,我将coredata保存在后台方法(父-子)中,但获取是在主线程上完成的。所以我在fetch方法中遇到了死锁,有时应用程序会崩溃。我做错什么了吗?如何在不影响主线程的情况下改进save和fetch?我读过很多文档,但没有一个文档解释我如何在项目中使用这两种方法。如果这是一个错误的问题,请引导我找到正确的解决方案,并让我知道我的错误 -(ThreadInfo *)retrieveSolicitationInfoForThreadID:(NSString*)inThreadID; { NSStrin
-(ThreadInfo *)retrieveSolicitationInfoForThreadID:(NSString*)inThreadID;
{
NSString *loginUser=[[NSUserDefaults standardUserDefaults] valueForKey:@"currentUser"];
AppDelegate *sharedDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [sharedDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setReturnsObjectsAsFaults:NO];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"ThreadInfo"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *userPredicate = [NSPredicate predicateWithFormat:@"userEmail == %@",loginUser];
NSPredicate *threadPredicate = [NSPredicate predicateWithFormat:@"threadID == %@",inThreadID];
NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates: @[userPredicate, threadPredicate]];
[fetchRequest setPredicate:compoundPredicate];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:nil];
if(fetchedObjects.count!=0)
{
ThreadInfo *threadInfo=[fetchedObjects objectAtIndex:0];
return threadInfo;
}
return nil;
}
保存
-(void)updateThreadEntityWithSyncDetails:(NSMutableDictionary *)inDictionary
{
NSString *loginUser=[[NSUserDefaults standardUserDefaults] valueForKey:@"currentUser"];
AppDelegate *sharedDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [sharedDelegate managedObjectContext];
// NSManagedObjectContext *writerContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
// [writerContext setPersistentStoreCoordinator:[sharedDelegate persistentStoreCoordinator]];
// create main thread MOC
context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
context.parentContext = writerContext;
NSManagedObjectContext *contextforThread = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
contextforThread.parentContext = context;
[contextforThread performBlock:^{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setReturnsObjectsAsFaults:NO];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"ThreadInfo"
inManagedObjectContext:contextforThread];
[fetchRequest setEntity:entity];
NSPredicate *userPredicate = [NSPredicate predicateWithFormat:@"userEmail == %@",loginUser];
NSPredicate *threadPredicate = [NSPredicate predicateWithFormat:@"threadID == %@",[inDictionary valueForKey:@"thread"]];
NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates: @[userPredicate, threadPredicate]];
[fetchRequest setPredicate:compoundPredicate];
NSArray *fetchedObjects = [contextforThread executeFetchRequest:fetchRequest error:nil];
for (ThreadInfo *threadInfo in fetchedObjects)
{
if([[inDictionary allKeys] containsObject:@"userEmail"])
{
if([inDictionary valueForKey:@"userEmail"]!=[NSNull null])
{
threadInfo.userEmail=[inDictionary valueForKey:@"userEmail"];
}
}
if([[inDictionary allKeys] containsObject:@"badgeValue"])
{
if([inDictionary valueForKey:@"badgeValue"]!=[NSNull null])
{
threadInfo.badgeValue=[inDictionary valueForKey:@"badgeValue"];
}
}
if([[inDictionary allKeys] containsObject:@"choice4Percentage"])
{
if([inDictionary valueForKey:@"choice4Percentage"]!=[NSNull null])
{
threadInfo.choice4Percentage=[inDictionary valueForKey:@"choice4Percentage"];
}
}
if([[inDictionary allKeys] containsObject:@"choice5Percentage"])
{
if([inDictionary valueForKey:@"choice5Percentage"]!=[NSNull null])
{
threadInfo.choice5Percentage=[inDictionary valueForKey:@"choice5Percentage"];
}
}
}
NSError *error;
if(![context save:&error]) {
NSLog(@"Child error : %@",error);
}
[context performBlock:^{
NSError *error;
if(![context save:&error]) {
NSLog(@"%@",error);
}
}];
}];
}
面对coreData和multiplyThreads等问题,您应该在相应的方法中添加以下代码:
[[NSNotificationCenter defaultCenter] addObserver: cdm.managedObjectContext selector: @selector(mergeChangesFromContextDidSaveNotification:) name:NSManagedObjectContextDidSaveNotification object: nil];
然后coreData在一个线程中更改,它将立即在使用coreData的另一个线程中更新它
希望答案对你有帮助 问题在于你的取回。您正在获取两个字符串,我猜您的商店中有大量实体。获取性能是问题的100% A) 如果可以避免,则不应进行字符串比较 B) 你不应该做两个字符串比较 您的数据模型需要重构。对一个包含大量实体的表进行两个字符串比较,无论发生什么情况,结果都会很糟糕 更新 你的数据结构不好。我不知道有多少种方式可以这样说。理想情况下,您希望使用整数或其他数字结构作为唯一标识符 由于您没有告诉我/我们您正在处理的实体有多少,我只能猜测您的数量很大。预期的结果如何?一个?还是很多?这是否是您正在处理的唯一约束?如果不是,为什么没有来自服务器的唯一约束?如果这是一个唯一的约束,为什么不按照我的建议限制获取大小 你没有给我任何信息,只是希望我能神奇地解决你的问题 您可以尝试将其缩减为一个字符串,但您要问的是me您的数据将如何运行。测试一下。你有仪器和数据。改变现状并比较结果 琴弦很贵。他们一直是,也将永远是 更新 由于这是一个独特的约束,您可以帮自己一个大忙,只需稍微更改一下代码:
- (ThreadInfo *)retrieveSolicitationInfoForThreadID:(NSString*)inThreadID;
{
NSString *loginUser = [[NSUserDefaults standardUserDefaults] valueForKey:@"currentUser"];
AppDelegate *sharedDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [sharedDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"ThreadInfo"];
[fetchRequest setReturnsObjectsAsFaults:NO];
//Since there is every only one tell SQL to stop looking after one
[fetchRequest setFetchBatchSize:1];
/* Change these to your single constraint
NSPredicate *userPredicate = [NSPredicate predicateWithFormat:@"userEmail == %@",loginUser];
NSPredicate *threadPredicate = [NSPredicate predicateWithFormat:@"threadID == %@",inThreadID];
NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates: @[userPredicate, threadPredicate]];
[fetchRequest setPredicate:compoundPredicate];
*/
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(@"Error fetching: %@\n%@", [error localizedDescription], [error userInfo]);
abort();
}
return [fetchedObjects lastObject];
}
设置提取限制将导致存储停止查找第一个匹配项,从而缩短提取时间。将其移动到单个字符串还可以减少提取时间
今后,在这种情况下避免使用字符串。执行整数主键的速度非常快,可以完全避免此性能问题。您的意思是在获取方法中?我的意思是,您的崩溃可能是两个线程操作coreData导致崩溃。先生,这就是问题所在,但我不清楚如何改进获取,因为我需要比较两个字符串。你能给我推荐一些方法或逻辑吗?方法真的很简单,不要做两个字符串与大量实体的比较。这是非常昂贵的。重新设计数据。你可以通过反复喊取数限制为1(假设你在寻找一个唯一的)来给它贴上绷带,看看这是否能改善它。您也可以在实体中索引这两个特性,但这两个特性都是止动间隙。稍后您的数据中有一个错误的设计。异步获取没有帮助,因为获取是问题所在。它将始终阻止
NSPersistentStoreCoordinator
,这是您的核心问题。限制批量大小可能会有所帮助,但不能保证。你需要测试一下。您真正需要做的是修复数据结构。搜索两个字符串是无效的。一直都是,永远都是。批更新是在iOS 8中引入的,而不是在iOS 7中引入的。考虑到您面临的问题,我不建议使用该API,因为它有许多与之相关的风险。