我只是想弄清楚核心数据私有上下文。我正在尝试使用私有上下文(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秒钟,UI一直没有响应。我想知道为什么吗?

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

//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;
}

最佳答案

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

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

另一种解决方案是重置mainContext并重新加载所有tableViews(您不会一次向用户显示所有20k条记录)。

关于ios - iOS:核心数据performBlock使UI无响应,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25115563/

10-09 23:49
查看更多