【问题标题】:iOS CoreData batch insert?iOS CoreData 批量插入?
【发布时间】:2011-05-07 22:47:17
【问题描述】:

在我的 iPhone 应用程序中,我需要在 Core Data 中插入大约 2000 条记录,然后用户才能使用应用程序的任何功能。我正在将记录从本地 JSON 文件加载到 CoreData 中。此过程需要很长时间(2.5 分钟以上),但只需执行一次(或每打开约 10 个应用程序以获取更新数据)。

Core Data 有批量插入吗?我怎样才能加快这个插入过程?

如果我无法使用 Core Data 加快速度,还有哪些其他推荐选项?

【问题讨论】:

    标签: iphone core-data ios


    【解决方案1】:

    查看核心数据编程指南中的Efficiently Importing Data 章节。

    我目前遇到和你一样的问题,只是我要插入 10000 个对象,大约需要 30 秒,这对我来说仍然很慢。我正在对插入到上下文中的每 1000 个托管对象执行 [managedObjectContext save](换句话说,我的批量大小为 1000)。我已经尝试了 30 种不同的批量大小(从 1 到 10000),在我的情况下,1000 似乎是最佳值。

    【讨论】:

    • 啊,我正在为每个项目进行保存。我不知道我不必在每个之后保存。将save 调用移到我的循环之外使它更快!低至约 5 秒
    • 这也可能具有潜在的节能影响。我注意到,在开始使用核心数据并一个接一个地插入约 30000 个对象后,我的应用程序开始以 1 次插入/秒的速度在 9 小时内多消耗约 20% 的电池寿命!
    【解决方案2】:

    当我遇到这个问题时,我正在寻找a similar question 的答案。 @VladimirMitrovic 当时的回答很有帮助,因为我知道我不应该每次都保存上下文,但我也在寻找一些示例代码。

    现在我有了它,我将提供下面的代码,以便其他人可以看到执行批量插入的情况。

    // set up a managed object context just for the insert. This is in addition to the managed object context you may have in your App Delegate.
    let managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = (UIApplication.sharedApplication().delegate as! AppDelegate).persistentStoreCoordinator // or wherever your coordinator is
    
    managedObjectContext.performBlock { // runs asynchronously
    
        while(true) { // loop through each batch of inserts. Your implementation may vary.
    
            autoreleasepool { // auto release objects after the batch save
    
                let array: Array<MyManagedObject>? = getNextBatchOfObjects() // The MyManagedObject class is your entity class, probably named the same as MyEntity
                if array == nil { break } // there are no more objects to insert so stop looping through the batches
    
                // insert new entity object
                for item in array! {
                    let newEntityObject = NSEntityDescription.insertNewObjectForEntityForName("MyEntity", inManagedObjectContext: managedObjectContext) as! MyManagedObject
                    newObject.attribute1 = item.whatever
                    newObject.attribute2 = item.whoever
                    newObject.attribute3 = item.whenever
                }
            }
    
            // only save once per batch insert
            do {
                try managedObjectContext.save()
            } catch {
                print(error)
            }
    
            managedObjectContext.reset()
        }
    }
    

    【讨论】:

    • @AbhishekThapliyal,我没有学过 Obj-C,所以我不会。但是,我知道该怎么做,我建议您在这个问题上添加自己的答案。
    • @AbhishekThapliyal,由于我无法验证 Objective-C 代码,您可以将其添加为单独的答案吗?我很乐意支持它。
    【解决方案3】:

    目标-C

    @Suragch anwser 的版本

    NSManagedObjectContext * MOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    MOC.persistentStoreCoordinator = YOURDB.persistentStoreCoordinator;
    [MOC performBlock:^{ 
       // DO YOUR OPERATION
     }];
    

    【讨论】:

      【解决方案4】:

      我非常喜欢@Suragch 的回答。这是它的 Objective-C 版本。

          NSManagedObjectContext *managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSPrivateQueueConcurrencyType];
          managedObjectContext.persistentStoreCoordinator = [[UIApplication sharedApplication].delegate.persistentStoreCoordinator];
      
          [managedObjectContext performBlock:^{
              while (true) {
                  @autoreleasepool {
                      // Code that creates autoreleased objects.
                      NSArray *batchObjects = [self getNextBatchOfObjects];
      
                      if (!batchObjects) {
                          break;
                      }
      
                      for (id item in batchObjects) {
                          MyEntity *newItem = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntity" inManagedObjectContext:managedObjectContext];
                          newObject.attribute1 = item.whatever;
                          newObject.attribute2 = item.whoever
                          newObject.attribute3 = item.whenever
                      }
                  }
      
                  // only save once per batch insert
                  NSError *error = nil;
                  [managedObjectContext save:&error];
                  [managedObjectContext reset];
              }
          }];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-04
        • 2014-09-17
        • 1970-01-01
        • 1970-01-01
        • 2011-02-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多