私有队列ManagedObjectContext

时间:2015-08-18 08:12:02

标签: ios core-data concurrency

我有以下核心数据堆栈:

  1. 带有NSMainQueueConcurrencyType
  2. 的主要NSManagedObjectContext
  3. NSManagedObjectContexts的多个临时NSPrivateQueueConcurrencyType(按需创建)。他们的父managedObjectContext设置为主要的managedObjectContext
  4. 到目前为止,我使用主要的managedObjectContext进行提取,使用私有的managedObjectContexts进行数据导入,因为要保存很多数据并且我不想阻止主线程。到目前为止,这对我来说非常好。

    现在我想实现我的应用搜索大量数据的全文搜索。我知道这在计算上是昂贵的,因此我想在后台执行此操作。

    - (void)filterConfigurationsInBackground
    {
        NSManagedObjectContext *temporaryContext = [[MVADataManager sharedInstance] privateContext];
        [temporaryContext performBlock:^{
           NSArray *filteredConfigurationsObjects =
           [temporaryContext executeFetchRequest:request error:&error];
           NSArray *filteredConfigurationsObjectIDs = [filteredConfigurationsObjects valueForKey:@"objectID"];
    
        NSManagedObjectContext *mainContext = [[MVADataManager sharedInstance] managedObjectContext];
        [mainContext performBlock:^{
            NSMutableArray *result = [NSMutableArray array];
    
        for (NSManagedObjectID *objectID in filteredConfigurationsObjectIDs)
        {
            NSError *error = nil;
            NSManagedObject *configuration = [context existingObjectWithID:objectID error:&error];
            if (configuration == nil)
            {
                DLog(@"Invalid objectID: %@", [error localizedDescription]);
            }
            else
            {
                [result addObject:configuration];
            }
        }
    
        [self setFilteredConfigurations:result];
    
            if ([self.tableView numberOfSections] == 1)
            {
                [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0]
                              withRowAnimation:UITableViewRowAnimationAutomatic];
            }
            else
            {
                [self.tableView reloadData];
            }
            [self updateTitle];
        }];
    }];
    }
    

    这确实有效,但是获取非常慢并且UI冻结了,这显然不应该发生。我的理解是,由于我在私有队列上执行实际的提取和过滤,因此根本不应该阻塞主线程。时间分析器没有帮助,只显示99%的“主”运行时间。为什么这段代码会阻塞主线程?

    更新1

    通过设置断点,我发现了对objectIDs的获取是代码中减慢一切的一部分。在断点处,调试器显示我们在后台线程上,UI冻结。 Xcode中的CPU报告显示,所有工作都在主线程上完成

    更新2和解决方法

    我找到了解决此问题的方法,但我仍然不知道究竟是什么原因造成的。我发现核心数据似乎很难与我的相当复杂的复合谓词进行全文搜索。 (除了全文搜索,我的谓词还对这些对象进行了一些基本的过滤。)

    因此,如果我首先使用基本过滤谓词执行核心数据提取,然后通过filteredArrayUsingPredicate:应用全文搜索谓词部分,则所有内容都可以在后台完成,而不会阻塞主线程。我仍然不知道为什么这个问题仍然存在,但我现在对这个解决方法感到满意。直到我有时间(和神经)深入研究,我才回答这个问题。

0 个答案:

没有答案