2010-04-09 7 views
7

我正在研究iPhone應用程序的一段代碼,它從服務器獲取一堆數據並在客戶端從它構建對象。它最終創建了大約40,000個對象。它們不會顯示給用戶,我只需要創建NSManagedObject的實例並將它們存儲到持久存儲中。內存高效地插入核心數據對象數組的方法

我錯在認爲唯一的方法來做到這一點是創建一個單一的對象,然後保存上下文?是最好一次創建對象,然後以某種方式將它們保存到上下文後創建並存儲在某些集合或數組中?如果是這樣,那麼可以顯示一些示例代碼來說明這是如何完成的,或者指示我如何編寫代碼的位置?

對象本身是相對直接的模型,具有字符串或整數屬性,並且不包含任何複雜的關係。

回答

5

在任何情況下,都不會在插入每個對象後保存,或準備好可怕的表演。

以下是我在首次啓動時用於填充核心數據存儲庫的代碼。

#define MAX_UNSAVED_AIRPORTS_BEFORE_SAVE 1000 
int numAirports = 0; 
int numUnsavedAirports = MAX_UNSAVED_AIRPORTS_BEFORE_SAVE; // *** bug. see below 
for (NSDictionary *anAirport in initialAirports) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    Airport *newAirport = [NSEntityDescription insertNewObjectForEntityForName:@"Airport" inManagedObjectContext:managedObjectContext]; 

    newAirport.city   = [anAirport objectForKey:@"city"]; 
    newAirport.code   = [anAirport objectForKey:@"code"]; 
    newAirport.name   = [anAirport objectForKey:@"name"]; 
    newAirport.country_name = [anAirport objectForKey:@"country_name"]; 
    newAirport.latitude  = [NSNumber numberWithDouble:[[anAirport objectForKey:@"latitude"] doubleValue]]; 
    newAirport.longitude = [NSNumber numberWithDouble:[[anAirport objectForKey:@"longitude"] doubleValue]]; 
    newAirport.altitude  = [NSNumber numberWithDouble:[[anAirport objectForKey:@"altitude"] doubleValue]]; 

    numAirports++; 
    numUnsavedAirports++; 
    if (numUnsavedAirports >= MAX_UNSAVED_AIRPORTS_BEFORE_SAVE) { 
     if (![managedObjectContext save:&error]) { 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      abort(); 
     } 
     numUnsavedAirports = 0; 
    } 
    [pool release]; 
} 

另外不要忘記在循環後最後一次保存一次。

另外要注意,一個bug的存在,將導致崩潰,如果所有三個下列條件都滿足:

  1. 資源庫是空的
  2. 你有段一個UITableView
  3. 你首先保存保存多個對象。

在上面的代碼的解決方法是初始化numUnsavedAirportsMAX_UNSAVED_AIRPORTS_BEFORE_SAVE爲了確保第一插入後的第一個保存情況。

我希望這會有所幫助。

1

創建單個對象並保存上下文可能會更好。

您有40k個對象。假設創建一個NSManagedObject需要x個時間單位。 40kx時間單位可能是可測量的。在創建對象時,用戶可能因某種原因退出應用程序;用戶是不可預知的。下次您的應用程序啓動後,您將再次完成整個過程。創建第39,999個對象僅僅是爲了讓用戶退出應用程序並失去所有這些工作並不可取。

如果您的應用程序要創建每個對象並保存,則可以加快此過程的速度。應用程序啓動並檢查它是否能夠在上次運行時完成任務。如果任務不完整,它可能會嘗試提取停止的地方。

單個對象的創建和保存方法可能需要較長時間才能完成,但完成該任務的可能性較大。

就內存消耗而言,這也可以最大限度地減少應用程序的內存狀態。上下文不跟蹤內存中的40k對象。

+2

分別保存每個對象會產生可怕的表現。 – 2010-04-10 00:27:20

3

在每個對象之後保存會產生非常差的性能。您應該每隔100次就會有一次保存的平衡(測試將確定最佳位置),然後在用戶退出時跟蹤處理過程中的位置。

您可以在退出時獲得存儲狀態的時間,以便您可以輕鬆地在數據處理中存儲您的位置(保存5個塊),然後從您離開的位置重新找回。

單獨保存每個對象都會敲擊磁盤並減慢應用程序的爬行速度。

+0

除了這個正確的建議之外,還應考慮在保存後重置ManagedObjectContext以減少內存佔用量。但請注意,重置上下文會使您在此環境中失去任何中間結果。例如。批量獲取結果也消失了。 – Bjinse 2013-02-19 08:59:03

+0

相關的Apple文檔位於:https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html – Bjinse 2013-02-19 09:08:03