iOS:核心数据performBlock使UI无法响应

时间:2014-08-04 09:30:50

标签: ios objective-c core-data

我只想清楚核心数据私有环境。我试图使用私有上下文(NSPrivateQueueConcurrencyType)插入20k记录。但是,只要“插入20k记录”按钮被点击,UI线程就会挂起。

- (IBAction)insertRecords:(id)sender {


[[CoreDataStore privateContext] performBlock:^{

    NSLog(@"Starting to insert 20k records...");
    for (int i = 0 ; i < 20000; i++)
    {
        NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:[CoreDataStore privateContext]];
        [newManagedObject setValue:[NSDate date] forKey:@"time"];
    }
    NSError * error = nil;
    NSLog(@"Inserted 20k records to managed object context");
    [[CoreDataStore privateContext] save:&error];
    NSLog(@"Save context command fired");

}];

NSLog(@"returning from insert method");
}

来自私有上下文的更改正在合并到主上下文

- (void)contextDidSavePrivateQueueContext:(NSNotification *)notification
{
    @synchronized(self) {

    [self.mainContext performBlock:^{
        NSLog(@"merging changes to main context.....");
        [self.mainContext mergeChangesFromContextDidSaveNotification:notification];
        NSLog(@"merged changes to main context");
    }];
}
}

当我按下插入按钮时,下面是日志窗口输出:

2014-08-04 14:54:12.431 CoreDataDrillDown[11323:90b] returning from insert method
2014-08-04 14:54:12.431 CoreDataDrillDown[11323:1403] Starting to insert 20k records...
2014-08-04 14:54:12.506 CoreDataDrillDown[11323:1403] Inserted 20k records to managed object context
2014-08-04 14:54:12.785 CoreDataDrillDown[11323:90b] merging changes to main context.....
2014-08-04 14:54:12.786 CoreDataDrillDown[11323:1403] Save context command fired
2014-08-04 14:54:27.019 CoreDataDrillDown[11323:90b] merged changes to main context

超过15秒,用户界面反应迟钝。我想知道原因?

使用https://stackoverflow.com/users/817182/thom-ekhttps://stackoverflow.com/users/2128900/micha%c5%82-ciuba建议的以下方法,插入很快,不会冻结用户界面,但更改不会保存到磁盘,不确定原因。

//writerContext has persistent store coordinator, so it should write data to disk but it 
//is not writing any changes to disk.???????
 -(NSManagedObjectContext *)writerContext
    {
      if (!_writerContext)
    {
        _writerContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        _writerContext.persistentStoreCoordinator  =  [(AppDelegate *)[[UIApplication sharedApplication] delegate] persistentStoreCoordinator];
    }
    return _writerContext;
}
//mainContext is being used with NSFetchedResultController
-(NSManagedObjectContext *)mainContext
{
    if (!_mainContext)
    {
        _mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        _mainContext.parentContext = [self writerContext];
    }
    return _mainContext;
}

//performBlock is being called on privateContext
-(NSManagedObjectContext *)privateContext
{
    if (!_privateContext)
    {
        _privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        _privateContext.parentContext = [self mainContext];
    }
    return _privateContext;
}

1 个答案:

答案 0 :(得分:1)

主要问题是mainContext仍然与mainQueue绑定,因此它将等待这个巨大的合并。

有关于异步保存的好文章:CocoaneticsObjC.io

其他解决方案只是重置mainContext并重新加载所有tableViews(您不会立即向用户显示所有20k记录)。