1

正如標題IM與被塗抹在不同的後臺線程對象(XML解析)多線程核心數據 - NSManagedObject無效

在我的後臺線程我做這個

managedContext = [[NSManagedObjectContext alloc] init]; 
[managedContext setUndoManager:nil]; 

[managedContext setPersistentStoreCoordinator: [[DataManager sharedManager] persistentStoreCoordinator]]; 

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
[nc addObserver:self 
     selector:@selector(mergeChanges:) 
      name:NSManagedObjectContextDidSaveNotification 
      object:managedContext]; 


NSMutableArray *returnSource = [[self parseDocument:doc] retain]; 


[managedContext save:&error]; 

if (error) { 
    NSLog(@"saving error in datafeed"); 
} 

[managedContext reset]; 

[self performSelectorOnMainThread:@selector(parseCompleteWithSource:) withObject:returnSource waitUntilDone:YES]; 
核心數據應用工作

的合併方法是這樣的:

NSManagedObjectContext *mainContext = [[DataManager sharedManager] managedObjectContext]; 

// Merge changes into the main context on the main thread 
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) 
           withObject:notification 
          waitUntilDone:YES]; 

[[NSNotificationCenter defaultCenter] removeObserver:self]; 

我認爲合併是成功的,但因爲我想在一個的UITableView顯示它總是告訴我牛逼帽子我的對象是無效這是可以預料的,因爲

[managedContext reset]; 

如果我想要做的就是證明這是目前在數據庫中的項目,在後臺解析XML和多數民衆贊成在完成我想要更新帶有新/更新對象的UITableView。我該怎麼做,我可以「更新」對象到其他上下文莫名其妙或合併不正確?

我是否需要在主ObjectContext中定義特定的內容? 我試過不同mergepolicies沒有任何運氣。

希望你能幫助我,謝謝!

+0

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/Concurrency.html –

回答

3

我相信你的問題是returnSource數組的內容。如果這是一堆NSManagedObject實例,那麼它們將由後臺線程上下文在後臺線程上創建。

您致電-[NSManagedObjectContext reset]將使其無效,因爲這是您明確告訴上下文執行的操作。但這不是大問題。

然後,您繼續將數組發送到主線程,通過線程邊界傳遞NSManagedObject實例,並且上下文之間是一個很大的禁忌。

你需要做的是:

  1. 創建具有NSManagedObjectID S中的NSManagedObject的數組。
  2. 通過線程邊界發送對象ID數組。
  3. 使用NSManagedObject從具有上下文的新線程上的託管對象ID重新創建數組。

我已經取得了一些核心數據的幫手,以下三個的規則(你寫的東西,第三次,使其一般)

最重要的是,我隱藏了爲每個線程管理不同的託管對象上下文,處理通知以及所有垃圾的複雜性。相反,我已經介紹了線程本地上下文的概念。基本上懶洋洋地創建了NSManagedObjectContext實例,它們在當前線程退出時自動註冊更新和清理。

正常使用情況:

NSManagedObjectCotext* context = [NSManagedObjectCotext threadLocalContext]; 
// Do your stuff!! 
NSError* error = nil; 
if (![context saveWithFailureOption:NSManagedObjectContextCWSaveFailureOptionThreadDefault 
           error:&error]) 
{ 
    // Handle error. 
} 

完整的源代碼,包括在覈心數據解析來自apple.com的新聞RSS,並將其存儲一個示例應用程序,可以在這裏找到:https://github.com/jayway/CWCoreData

+0

-1雖然您的代碼可能有用,但它並不是真正解決此特定問題的答案。 – TechZen

+0

@ TechZen - 你是對的,所以我擴大了我的答案。 – PeyloW

+0

嘿!謝謝,我自己想出了這個,並且完全按照你在這裏描述的內容做了。 :) – Patrick

1

在這種情況下,在背景上下文中調用reset沒有任何理由,因爲它無論如何都會隨後臺線程消失,並且在任何情況下都不會再使用它。當您希望上下文忘記之前的步驟時,通常使用reset進行撤銷管理。

您的主要問題在於您的後臺線程被配置爲從它創建的託管對象上下文接收通知。這是毫無意義的。

相反,您需要註冊tableview控制器(在前線程上)以從後臺線程的上下文接收NSManagedObjectContextDidSaveNotification。這樣,當後臺上下文保存時,前臺/主上下文將使用觸發TableView更新的新數據自行更新。