我只想清楚核心数据私有环境。我试图使用私有上下文(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-ek和https://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;
}
答案 0 :(得分:1)
主要问题是mainContext仍然与mainQueue绑定,因此它将等待这个巨大的合并。
有关于异步保存的好文章:Cocoanetics和ObjC.io。
其他解决方案只是重置mainContext并重新加载所有tableViews(您不会立即向用户显示所有20k记录)。