2

我有一个巨大的 NSArray(4.000.000 个对象),我想保存到 Core Data 中。因为我使用 ARC 并且自动释放池可能会变得太大,所以我将进程划分为多个循环(因此自动释放池可以有机会自行耗尽)。

在以下代码中,我使用管理器 (clMan) 从数组(区域)内的字典中添加项目。字典包含两个字符串字段,它们被解析为标量整数。

将数据划分为多个循环的代码

int loopSize = 50000;
int loops = 0;
int totalRepetitions = regions.count;
loops = totalRepetitions / loopSize;
int remaining = totalRepetitions % loopSize;


loops += 1;


for (int i = 0; i < loops; i++) {

    int k = 0;
    if (i == 0) k = 1;

    if (i == (loops - 1))
    {
            // Last loop

            for (long j = i * loopSize + k; j < i * loopSize + remaining; j++) {
                [clMan addItemWithData:[regions objectAtIndex:j]];
            }
            [clMan saveContext];
            break;

    }

    // Complete loops before the last one
        for (long j = i * loopSize + k; j < (i + 1) * loopSize; j++) {
            [clMan addItemWithData:[regions objectAtIndex:j]];
        }
        [clMan saveContext];
        NSLog(@"Records added : %d", i * loopSize);

}
NSLog(@"Finished adding into core data");

将数据添加到核心数据中的代码:

-(void)addItemWithData:(NSDictionary *)data
{

    MyRegion *region = [NSEntityDescription
                                              insertNewObjectForEntityForName:@"MyRegion"
                                              inManagedObjectContext:self.context];


    region.index = [((NSString *)[data objectForKey:REGION_INDEX]) intValue];
    region.id = [((NSString *)[data objectForKey:REGION_ID]) intValue];

} 

程序在达到 1 500 000 索引时崩溃。由于解析问题/逻辑,崩溃似乎没有发生。

谁能告诉我我的逻辑是否错误,或者在 CoreData 中添加这么多数据的正确方法是什么?

4

1 回答 1

3

在每个循环之后,尝试调用NSManagedObjectContext.reset以“忘记” MOC 中的本地副本。否则,这些可能不会被清除并导致问题。

iCloud 上的 WWDC 2012 代码示例有一种方法,称为seedStore将本地核心数据 SQL 数据库迁移到 iCloud 数据库 - 使用 5000 条记录的批量大小,其中明确指出:

if (0 == (i % batchSize)) {
    success = [moc save:&localError];
    if (success) {
        /*
           Reset the managed object context to free the memory for the inserted objects
           The faulting array used for the fetch request will automatically free
           objects with each batch, but inserted objects remain in the managed
           object context for the lifecycle of the context
         */
        [moc reset];
    } else {
        NSLog(@"Error saving during seed: %@", localError);
        break;
    }
}

(这i是批次的当前索引,因此i % batchSize == 0如果我们开始一个新批次)

于 2013-04-03T07:30:17.107 回答