Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/122.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 在后台线程上保存coredata会导致获取陷入死锁和崩溃_Ios_Objective C_Multithreading_Core Data - Fatal编程技术网

Ios 在后台线程上保存coredata会导致获取陷入死锁和崩溃

Ios 在后台线程上保存coredata会导致获取陷入死锁和崩溃,ios,objective-c,multithreading,core-data,Ios,Objective C,Multithreading,Core Data,我将coredata保存在后台方法(父-子)中,但获取是在主线程上完成的。所以我在fetch方法中遇到了死锁,有时应用程序会崩溃。我做错什么了吗?如何在不影响主线程的情况下改进save和fetch?我读过很多文档,但没有一个文档解释我如何在项目中使用这两种方法。如果这是一个错误的问题,请引导我找到正确的解决方案,并让我知道我的错误 -(ThreadInfo *)retrieveSolicitationInfoForThreadID:(NSString*)inThreadID; { NSStrin

我将coredata保存在后台方法(父-子)中,但获取是在主线程上完成的。所以我在fetch方法中遇到了死锁,有时应用程序会崩溃。我做错什么了吗?如何在不影响主线程的情况下改进save和fetch?我读过很多文档,但没有一个文档解释我如何在项目中使用这两种方法。如果这是一个错误的问题,请引导我找到正确的解决方案,并让我知道我的错误

-(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,因为它有许多与之相关的风险。