2011-11-30 140 views
0

我正在iPad中開發客戶端服務器應用程序。我需要保存服務器發送給我的大量數據。它給我一個很長的字符串,我必須把它分解成小記錄並保存在覈心數據中。它總共發送了20條消息,每條消息大約有100條記錄。在線程中保存核心數據

現在的問題是用戶必須等待所有消息保存到核心數據中,然後才能解除UI,因爲它的所有消息都在主線程中運行。

問題,我可以接收來自服務器的消息,並拋出數據分解並保存到核心數據到線程中嗎?當上下文保存時,我不斷收到sigbart錯誤。我檢查了核心數據,它在遇到該錯誤之前節省了大約4條記錄。

多個線程可以同時訪問/保存到核心數據嗎?

對不起,我真的迷路了。嘗試了開源的魔法記錄,但它仍然有錯誤。

回答

0

核心數據管理的對象上下文不是線程安全的。雖然您可以擁有單個Core Data存儲,但您需要爲每個線程創建一個單獨的託管對象上下文。如果需要在線程之間傳遞對管理對象的引用,則需要傳遞對象ID,然後從本地管理對象上下文中讀取對象,而不是嘗試傳遞對象本身。

這樣做將使您能夠使用核心數據保存在後臺。

當保存後臺線程時要小心,但應用程序可能在後臺線程完成保存之前退出。見this discussion

+0

您的意思是說核心數據一次只能訪問一個?我對xcode dev很陌生.. – kraitz

+0

不,我的意思是你通過託管對象上下文訪問核心數據,你可以在一個應用程序中擁有多個託管對象上下文,並且每個線程都必須有自己的專用託管對象上下文。 :) –

+0

我在應用程序委託中有一個託管對象上下文。如何在新線程上運行的方法中聲明新的方法? – kraitz

0

由於核心數據需要一個管理的每個線程對象上下文,一個可能的解決方案來跟蹤每線程上下文的全球經理,然後跟蹤保存通知,並傳播到所有線程:

假設:

@property (nonatomic, strong) NSDictionary* threadsDictionary; 

這裏是如何得到(每線程)管理對象:

- (NSManagedObjectContext *) managedObjectContextForThread { 

// Per thread, give one back 
NSString* threadName = [NSString stringWithFormat:@"%d",[NSThread currentThread].hash]; 

NSManagedObjectContext * existingContext = [self.threadsDictionary objectForKey:threadName]; 
if (existingContext==nil){ 
    existingContext = [[NSManagedObjectContext alloc] init]; 
    [existingContext setPersistentStoreCoordinator: [self persistentStoreCoordinator]]; 
    [self.threadsDictionary setValue:existingContext forKey:threadName]; 
} 

return existingContext; 

}

在您的全球經理的init方法的一些點(我用一個單):

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backgroundContextDidSave:)             name:NSManagedObjectContextDidSaveNotification             object:nil]; 

然後接收保存通知和傳播到所有其他管理上下文對象:

- (void)backgroundContextDidSave:(NSNotification *)notification { 
    /* Make sure we're on the main thread when updating the main context */ 
    if (![NSThread isMainThread]) { 
     [self performSelectorOnMainThread:@selector(backgroundContextDidSave:) 
           withObject:notification 
          waitUntilDone:NO]; 
     return; 
    } 

    /* merge in the changes to the main context */ 
    for (NSManagedObjectContext* context in [self.threadsDictionary allValues]){ 
      [context mergeChangesFromContextDidSaveNotification:notification]; 
    } 
} 

(爲了清晰起見,刪除了一些其他方法)