Ios 如何在背景中创建多个对象?

Ios 如何在背景中创建多个对象?,ios,multithreading,core-data,magicalrecord,Ios,Multithreading,Core Data,Magicalrecord,我使用的是MagicalRecord 2.0.3,我真的不知道如何在后台保存数据 根据文档,类似的东西应该可以工作: [MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) { // Do this hundreds of times [MyObject createInContext:localContext]; }]; 但是,不会将任何内容保存到数据库中。我见过很多人发

我使用的是MagicalRecord 2.0.3,我真的不知道如何在后台保存数据

根据文档,类似的东西应该可以工作:

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) {
    // Do this hundreds of times
    [MyObject createInContext:localContext];
}];
但是,不会将任何内容保存到数据库中。我见过很多人发布类似的解决方案:

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) {
    // Do this hundreds of times
    [MyObject createInContext:localContext];
} completion:^{
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [[NSManagedObjectContext defaultContext] saveNestedContexts];
    }];
}];
这确实会将我的数据保存到数据库中,但是由于保存发生在主线程上,所以我的应用程序有一段时间没有响应(对于我的数据集,大约3秒,这太长了)

我也尝试过这一点,但它在保存时也会阻塞:

self.queue = [[NSOperationQueue alloc] init];

[self.queue addOperationWithBlock:^{
    NSManagedObjectContext *localContext = [NSManagedObjectContext contextForCurrentThread];

    // Do this hundreds of times
    [MyObject createInContext:localContext];

    [localContext saveNestedContexts];
}];
最后,此代码具有相同的阻塞效果:

dispatch_queue_t syncQueue = dispatch_queue_create("Sync queue", NULL);
dispatch_async(syncQueue, ^{
    NSManagedObjectContext *localContext = [NSManagedObjectContext contextForCurrentThread];

    // Do this hundreds of times
    [MyObject createInContext:localContext];

    [[NSManagedObjectContext contextForCurrentThread] saveNestedContexts];
});

那么,解决这个问题的最佳方法是什么?我需要在后台创建数百个对象,应用程序需要保持响应。

MagicalRecord在后台工作时使用子上下文。这对于小的更改很有效,但在导入大量数据时会产生过多的主线程阻塞

方法是使用并行NSManagedObjectContext,并使用
NSManagedObjectContextDidSaveNotification
通知和
mergeChangesFromContextDidSaveNotification
方法进行合并。请参见此处的性能测试:

保存嵌套上下文时,必须将所有内容复制到父上下文。与此相反,未提取的对象(在您要合并到的上下文中)将不会被
mergeChangesFromContextDidSaveNotification
合并。这就是让它更快的原因

如果要在批量保存并使用NSFetchResultsController后立即显示这些结果,可能会遇到问题。有关解决方案,请参见以下问题:

有关更多性能提示,请查看以下问题:

创建自己的上下文

NSManagedObjectContext *importContext = [[NSManagedObjectContext alloc] 
                          initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[importContext setPersistentStoreCoordinator:yourPersistentStoreCoordinator];
[importContext setUndoManager:nil]; // For importing you don't need undo: Faster

// do your importing with the new importContext
// …

NSError* error = nil;
if(importContext.hasChanges) {
  if(![importContext save:&error]) {
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
  } 
}
确保正在侦听对托管对象上下文的保存

[[NSNotificationCenter defaultCenter] 
              addObserver:singleton 
                 selector:@selector(contextDidSave:)
                     name:NSManagedObjectContextDidSaveNotification object:nil];
在contextDidSave中:您自己合并更改

- (void) contextDidSave:(NSNotification*) notification
{
  if(![notification.object isEqual:self.mainContext]) {
    dispatch_async(dispatch_get_main_queue(), ^{
      [self.mainContext mergeChangesFromContextDidSaveNotification:notification];
    });
  }
}

托管对象上下文不是线程安全的,因此,如果您需要对Coredata对象执行任何类型的后台工作(即在不阻塞主UI的情况下执行长时间运行的导入/导出功能),您将希望在后台线程上执行此操作

在这些情况下,您需要在后台线程上创建一个新的托管对象上下文,迭代coredata操作,然后将更改通知主上下文

你可以在这里找到一个这样做的例子


新的嵌套上下文已经开始对MagicalRecord中的许多保存API造成严重破坏。虽然我知道这些问题,并且现在正在讨论一些修复方案,但我始终愿意接受建议。也许您最好在没有MR这样的框架的情况下使用核心数据?您有没有找到使用MagicalRecord的解决方案?我也有同样的问题(在后台更新时UI锁定),我找不到解决方案。谢谢最后,我从我的应用程序中删除了MagicalRecord。我现在使用的是,它的魔力小得多,而且似乎效果更好。MagicalRecord 2.1的性能更好吗?后台保存现在真的起作用了吗?这到底是怎么起作用的?我面临的问题是,由于要导入大量数据,我的主线程被阻塞。我正在使用MagicalRecord,但无法实现您在这里所写的内容。。。