2013-04-03 14 views
1

我有一個巨大的NSArray(4.000.000對象),我想保存到核心數據。 因爲我使用ARC並且autorelease池可能會變得太大,我將該進程劃分爲多個循環(所以autorelease池可能有機會耗盡自己)。如何在CoreData中正確添加大型數據集?

在下面的代碼中,我使用管理器(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中添加這些數據量的正確方法?

+0

你有沒有想過使用魔法記錄這個?它具有非常好的自動導入數組和字典數據的設置。 – Fogmeister

+0

除非你用'@autoreleasepool {}'來包裝它們,否則你的循環將無濟於事。您還需要像邁克爾羅斯在他的回答中所說的那樣「重置」MOC。 –

回答

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如果我們開始一個新批次)