我在背景方法(父子)中保存coredata,但是在主线程上完成提取。所以我在fetch方法中遇到了死锁,有时app崩溃了。我在做什么有什么不对吗?如何在不影响主线程的情况下改进保存和获取?我已经阅读了很多文档,但没有一个文档向我解释如何在项目中使用它们。如果这是一个错误的问题,请指导我正确的解决方案,并让我知道我的错误。
-(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);
}
}];
}];
}
答案 0 :(得分:3)
问题在于你的提取。您正在提取两个字符串,而我猜测的是您商店中的大量实体。您的抓取效果是您问题的100%。
A)如果可以避免,你不应该进行字符串比较 B)你不应该进行两次字符串比较
您的数据模型需要重构。对具有大量实体的表进行两次字符串比较无论如何都会表现不佳。
您的数据结构不好。我不知道有多少方法可以这么说。理想情况下,您需要整数或其他数字结构作为唯一标识符。
由于您没有告诉我/我们您正在处理多少实体,我只能猜测您有大量实体。如何预期男人的结果?一?还是很多?这是一个你正在反对的独特约束吗?如果没有,为什么没有来自您的服务器的唯一约束?如果它是一个独特的约束,为什么你没有像我建议的那样限制提取大小?
您没有向我提供任何信息,但希望我能够神奇地解决您的问题。
您可以尝试将其缩减为一个字符串,但是您要求我 您的数据的行为方式。测试一下。你有乐器,你有数据。改变一切并比较结果。
字符串很贵。他们一直都是,而且永远都是。
由于它是一个独特的约束,你可以自己做一个大忙,稍微改变你的代码:
- (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];
}
设置获取限制将导致存储停止查看第一个匹配,这将减少获取时间。将其移动到单个字符串也会缩短获取时间。
将来,在这种情况下避免使用字符串。执行整数主键的速度非常快,完全可以避免这种性能问题。
答案 1 :(得分:-1)
面对coreData和multiplyThreads等问题,您应该在相应的方法中添加以下代码:
[[NSNotificationCenter defaultCenter] addObserver: cdm.managedObjectContext selector: @selector(mergeChangesFromContextDidSaveNotification:) name:NSManagedObjectContextDidSaveNotification object: nil];
然后coreData在一个线程上更改,它将立即在另一个使用coreData的线程中更新它。
希望答案能帮到你!