我遇到的情况是我必须处理连续获取和保存请求。当我必须处理的数据量增加时,我的应用程序正在冻结。我的节省会立即更新到NSFetchedResultsController
的桌面视图。我试图通过使用示例代码来隔离我的问题,我在下面放了一些代码。冻结问题在这个地区。我将至少保存3000条记录。有人请帮我解决我的UI冻结问题。
这是运行项目的探查器日志:https://www.dropbox.com/s/tf1eiz3c5vnr0hq/Instruments10.trace.zip?dl=0
- (void)coreDataTest {
// Create NSManagedObjectModel and NSPersistentStoreCoordinator
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"momd"];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"store.sqlite"];
// remove old store if exists
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:[storeURL path]])
[fileManager removeItemAtURL:storeURL error:nil];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSPersistentStoreCoordinator *storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
[storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:nil
error:nil];
NSManagedObjectContext* masterContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[masterContext setPersistentStoreCoordinator:storeCoordinator];
// create the parent NSManagedObjectContext with the concurrency type to NSMainQueueConcurrencyType
_parentContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_parentContext setParentContext:masterContext];
// creat the child one with concurrency type NSPrivateQueueConcurrenyType
_childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_childContext setParentContext:_parentContext];
// create a NSEntityDescription for the only entity in this CoreData model: Test
NSEntityDescription *testDescription = [NSEntityDescription entityForName:@"Test"
inManagedObjectContext:_parentContext];
// perform a heavy write block on the child context
__block BOOL done = NO;
[_childContext performBlock:^{
for (int i = 0; i < 3000; i++){
Test *test = [[Test alloc] initWithEntity:testDescription
insertIntoManagedObjectContext:_childContext];
test.test = [NSString stringWithFormat:@"Test %d", i];
NSLog(@"Create test %d", i);
[_childContext save:nil];
done = YES;
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"Done write test: Saving parent");
[_parentContext save:nil];
NSFetchRequest *fr = [NSFetchRequest fetchRequestWithEntityName:@"Test"];
NSLog(@"Done: %d objects written", [[_parentContext executeFetchRequest:fr error:nil] count]);
[masterContext performBlock:^{
[masterContext save:nil];
// execute a fetch request on the parent to see the results
}];
});
}
}];
// execute a read request after 1 second
double delayInSeconds = 1.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
NSFetchRequest *fr = [NSFetchRequest fetchRequestWithEntityName:@"Test"];
[_parentContext performBlockAndWait:^{
NSLog(@"In between read: read %d objects", [[_parentContext executeFetchRequest:fr error:nil] count]);
}];
});
}
答案 0 :(得分:0)
尝试以下提高速度的步骤
1 - 使用NSFethedResultControler,它将帮助您在每次保存后自动重新加载数据,因为每次保存后都会调用其委托
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller{
[self fetchCoreDataArrayAfterSave];
}
2 - 尝试一次分批保存(100)
3 - NSMangedObjectContext的用户insertObject方法而不是save,save将在插入100个批处理后立即使用。
for (int i = 0; i <first 100; i++){
Test *test = [[Test alloc] initWithEntity:testDescription
insertIntoManagedObjectContext:_childContext];
test.test = [NSString stringWithFormat:@"Test %d", i];
[_childContext insertObject:test]
};
[_childContext save:nil];
4 - 在后台完成所有这些
5 - 使用批次来获取数据。
如果您无法理解任何一点,请随时提出。
答案 1 :(得分:0)
对于执行快速插入而不阻塞主线程使用上面的代码
//在Appdelegate中创建父上下文
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
[_managedObjectContext setUndoManager:nil];
}
return _managedObjectContext;
}
//在Appdelegate中创建子上下文
- (NSManagedObjectContext *)childManagedObjectContext
{
if (_childManagedObjectContext != nil) {
return _childManagedObjectContext;
}
_childManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_childManagedObjectContext setParentContext:_managedObjectContext];
return _childManagedObjectContext;
}
//现在执行保存操作
[UIAppDelegate.childManagedObjectContext performBlock:^{
//Fill Ur Daatbse (Insert)
for (int i=0; i<count; i++) {
[UIAppDelegate.childManagedObjectContext save:nil];
}
dispatch_sync(dispatch_get_main_queue(), ^{
[UIAppDelegate.managedObjectContext save:nil];
[UIAppDelegate hideProgressBar];
});
}];