2015-04-13 2 views
-1

Я получаю заблокированный UI даже метод parent-child, используемый для сохранения фона coredata. Приложение замерзает на 30-40 секунд. Я пробовал GCD, но он все еще застревает. Есть ли способ удалить это?Приложение получает зависание на 30-40 секунд

**appdelegate** 
    - (NSManagedObjectContext *)managedObjectContext 
{ 


if (_managedObjectContext != nil) { 
    return _managedObjectContext; 
} 


NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
if (coordinator != nil) { 
    //  _managedObjectContext = [[NSManagedObjectContext alloc] init]; 
    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 

    [_managedObjectContext setPersistentStoreCoordinator:coordinator]; 
} 
return _managedObjectContext; 
} 

Перед сбережением в DB я использовал для вызова другой функции, которая сохраняет словарь.

-(void)updateSolicitationWithSyncDetails:(NSDictionary *)inDictionary 
    { 


NSLog(@"updateSolicitationWithSyncDetails CALLED"); 

//NSDictionary *loDIct = [inDictionary objectForKey:@"body"]; 
NSMutableDictionary *paramDict=[NSMutableDictionary dictionaryWithDictionary:inDictionary]; 
NSString *userEmail=[[NSUserDefaults standardUserDefaults] valueForKey:@"currentUser"]; 

[paramDict setObject:[NSNumber numberWithBool:NO] forKey:@"isSystemMessage"]; 
[paramDict setObject:userEmail forKey:@"userEmail"]; 

if([[inDictionary allKeys] containsObject:@"d-activities"]) 
{ 
    NSMutableArray *activityArray=[NSMutableArray arrayWithArray:[inDictionary objectForKey:@"d-activities"]]; 
    //TODO:Check type 
    [self manageActivityArrayWithDetails:activityArray ForType:@"Domain"]; 
} 
if([[inDictionary allKeys] containsObject:@"g-activities"]) 
{ 
    NSMutableArray *activityArray=[NSMutableArray arrayWithArray:[inDictionary objectForKey:@"g-activities"]]; 
    //TODO:Check type 
    [self manageActivityArrayWithDetails:activityArray ForType:@"Feedback"]; 
} 
if([[inDictionary allKeys] containsObject:@"p-activities"]) 
{ 
    NSMutableArray *activityArray=[NSMutableArray arrayWithArray:[inDictionary objectForKey:@"p-activities"]]; 
    //TODO:Check type 
    [self manageActivityArrayWithDetails:activityArray ForType:@"Private"]; 
} 


if([[inDictionary allKeys] containsObject:@"replies"]) 
{ 
    [paramDict setObject:[NSNumber numberWithInteger:[[inDictionary valueForKey:@"replies"] integerValue]] forKey:@"responseCount"]; 
} 
NSDate *threadDate=[NSDate date]; 

if([[inDictionary allKeys] containsObject:@"created_at"]) 
{ 
    double timeInMilliSeconds =[[inDictionary objectForKey:@"created_at"] doubleValue]; 
    threadDate=[[IXNetworkDataManager sharedNetworkDataManager] retrieveDateFromInterval:timeInMilliSeconds];//Convert timeinterval to date 
} 
[paramDict setObject:threadDate forKey:@"threadDate"]; 
[paramDict setObject:[NSDate date] forKey:@"receivedDate"]; 
if([[inDictionary allKeys] containsObject:@"_id"]) 
{ 
    [paramDict setObject:[inDictionary objectForKey:@"_id"] forKey:@"thread"]; 
    [paramDict setObject:[inDictionary objectForKey:@"_id"] forKey:@"solicitation"]; 

} 
if([[inDictionary allKeys] containsObject:@"owned"]) 
{ 
    BOOL isOwned=[[inDictionary valueForKey:@"owned"] boolValue]; 
    if(isOwned) 
    { 
     [paramDict setObject:[NSNumber numberWithBool:YES] forKey:@"isRequester"]; 
    } 
    else 
    { 
     [paramDict setObject:[NSNumber numberWithBool:YES] forKey:@"isProvider"]; 

    } 



} 

if([[inDictionary allKeys] containsObject:@"body"]) 
{ 

    NSString *message=[[inDictionary objectForKey:@"body"] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 


    BOOL isDuplicate=[[IXDataBaseManager sharedNetworkDataManager] checkForExistenceOfThreadDetailsForSolicitationID:[inDictionary objectForKey:@"_id"]]; 


    if(!isDuplicate) 
    { 
     // int randomIndex=[[IXNetworkDataManager sharedNetworkDataManager] getIndexForColorImageForTab:@"OUT"]; 
     [paramDict setObject:message forKey:@"threadDescription"]; 

     //[paramDict setObject:[NSNumber numberWithInt:randomIndex] forKey:@"colorCode"]; 
     [[IXDataBaseManager sharedNetworkDataManager] insertToThreadEntityWithData:paramDict]; 
    } 
    else 
    { 
     [paramDict setObject:message forKey:@"messageDescription"]; 
     ThreadInfo *threadInfo=[[IXDataBaseManager sharedNetworkDataManager] retrieveSolicitationInfoForThreadID:[inDictionary objectForKey:@"_id"]]; 
     [paramDict setObject:threadInfo.threadID forKey:@"thread"]; 
     [[IXDataBaseManager sharedNetworkDataManager] updateThreadEntityWithSyncDetails:paramDict]; 
    } 

    } 



    } 

insertToThreadEntityWithData

 AppDelegate *sharedDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 
NSManagedObjectContext *context = [sharedDelegate managedObjectContext]; 
NSManagedObjectContext *contextforThread = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 

contextforThread.parentContext = context; 

[contextforThread performBlock:^{ 

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
[fetchRequest setReturnsObjectsAsFaults:NO]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"UserInfo" 
              inManagedObjectContext:context]; 
[fetchRequest setEntity:entity]; 
NSPredicate *threadPredicate = [NSPredicate predicateWithFormat:@"userEmail == %@",[inDictionary valueForKey:@"userEmail"]]; 
[fetchRequest setPredicate:threadPredicate]; 

NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:nil]; 

ThreadInfo *threadInfo = [NSEntityDescription 
          insertNewObjectForEntityForName:@"ThreadInfo" 
          inManagedObjectContext:context]; 

for (UserInfo *info in fetchedObjects) 
{ 

    if([[inDictionary allKeys] containsObject:@"userEmail"]) 
    { 
     if([inDictionary valueForKey:@"userEmail"]!=[NSNull null]) 
     { 
      threadInfo.userEmail=[inDictionary valueForKey:@"userEmail"]; 
     } 
    } 

    if([[inDictionary allKeys] containsObject:@"thread"]) 
    { 
     if([inDictionary valueForKey:@"thread"]!=[NSNull null]) 
     { 
      threadInfo.threadID=[inDictionary valueForKey:@"thread"]; 
     } 
    } 

      NSError *error; 
    if(![contextforThread save:&error]) { 
     NSLog(@"Child error : %@",error); 

    } 

    [context performBlock:^{ 
     NSError *error; 
     if(![context save:&error]) { 
      NSLog(@"%@",error); 
     } 
    }]; 
    }]; 

ответ

0

По-моему, вы делаете ряд принципиальных ошибок.

Ошибка, которая блокирует ваш пользовательский интерфейс приложения, заключается в том, что вы связываете свой NSPersistentStoreCoordinator в основной поток. Пользовательский интерфейс работает в основном потоке. Поэтому PSC должен работать вместе с основными операциями пользовательского интерфейса.

Вы должны рассмотреть возможность создания двух NSManagedObjectContext s в момент создания экземпляра вашего MOC & PSC.

  • Один на основе initWithConcurrencyType:NSMainQueueConcurrencyType
  • One на основе initWithConcurrencyType:NSPrivateQueueConcurrencyType

используется основной контекст очереди управляемого объекта (МОС) для обработки малых и частое сохранение изменений данных в МОЦ в главном потоке (к памяти), тем самым уменьшая до незначительного эффекта сохранения эффекта в пользовательском интерфейсе.

Вы используете частную очередь MOC для сохранения данных на диске в фоновом потоке - никакого влияния на пользовательский интерфейс.

Для этого, чтобы быть эффективным, вам необходимо:

  • связать ваш PSC к частной MOC,
  • сделать частный MOC родитель главного MOC,
  • сохраняются пользовательские изменения к данным в основном MOC,
  • При необходимости сохраните импортированные и/или большие наборы данных в дополнительном «локальном» MOC, являющемся дочерним элементом основного MOC, и
  • напишите собственный способ сохранения.

Просмотреть блок сохранения Я написал в this SO answer.

Пойдите, посмотрите, как это делает один из мастеров Core Data ... Marcus Zarra's entry in the Martiancraft Blog ... Я узнал все, что знаю по этому поводу, прочитав его книгу 2013 года о Core Data.

+0

Я уже использовал потоки с родительским потоком, но все еще застрял. – Jan

+0

Несомненно, вы использовали потоки родительского ребенка - запутанным способом. Если вы всегда правы, то зачем обращаться за помощью? То, что я предлагаю, намного проще, чем запутанный механизм, который вы реализовали. – andrewbuilder

+0

Я не так много опытен с многопоточными. можете ли вы изменить мой код? Так что я могу получить реальные проблемы. – Jan