0

我有一個核心數據應用程序,它具有文章數據結構&評論(一對多關係)。在NSOperation中設置核心數據關係... NSManagedObject已經失效

NSOperations管理不同線程上的下載和JSON解析,然後它使用mergeChangesFromContextDidSaveNotification將更改傳遞到保存它的主線程,並且fetchedResultsController負責處理tableView更改。

這些文章和評論的調用是在從服務器調用的單獨的API中進行的,每個API都有它自己的NSOperation來處理導入。 (它們基於Apple的RSSImporter類鬆散地構建,但已經針對JSON進行了修改)。每個操作都有自己的上下文,並使用fetchedResultsController中的storeCoordinator。

commentParser.articleObjectID = [article objectID]; 
commentParser.persistentStoreCoordinator = [[self.fetchedResultsController managedObjectContext] persistentStoreCoordinator]; 

我正在嘗試設置物品之間,並在的NSOperation關係的意見,我相信我通過將物品進入評論操作的objectID,然後使用該對象以下的最佳實踐通過執行以下操作:

Article *article = (Article *)[self.insertionContext objectWithID:articleObjectID]; 
Comment *aComment = (Comment *)[NSEntityDescription insertNewObjectForEntityForName:@"Comment" inManagedObjectContext:self.insertionContext]; 
[aComment setCommentArticle:article]; 

這似乎很好地工作,但要回根的viewController其中原創文章的的tableView的時候,我得到了以下錯誤消息:

* Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'The NSManagedObject with ID:0xdb24f30 has been invalidated.'

任何幫助,將不勝感激!

回答

2

您必須在創建它們的線程(對持久性存儲庫)中保存新的Core Data實體(或對現有實體的更改),然後將該對象ID傳遞到主線程,該線程上的NSManagedContext將使用該主線程objectID從持久性存儲中檢索對象。

已經看清楚了: http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html

所以一定要保存你在後臺線程創建的新對象(或改變對象)到的NSManagedObjectContext,然後一切都應該正常工作。

+0

嗨達米安。謝謝回覆!我在操作結束時保存了insertionContext(後臺線程moc),它將通知中的對象傳遞迴主線程,然後合併上下文。所以不要使用對象本身。我將objectID傳遞迴主線程並重新獲取? – 2011-04-13 15:37:51

+0

通常我會在mergeChangesFromContextDidSaveNotification中處理它。您可以發佈保存操作以及您的問題如何融入您的問題,並且能夠提供更有針對性的幫助? – Damien 2011-04-13 15:47:33

+0

你的問題觸發*關注*爲我的部分是:NSOperations管理在不同的線程下載和JSON解析然後使用mergeChangesFromContextDidSaveNotification通過在那裏的將更改保存到主線程和fetchedResultsController需要的的tableView變化照顧。 – Damien 2011-04-13 15:48:07

2

達米恩讓你走上正軌。下面是如何處理這個:

  1. 在你的主線程的對象被註冊爲NSManagedObjectContextDidSaveNotification

  2. NSOperation下載JSON並將其添加到操作中初始化的管理對象上下文,保存上下文時所有對象都被添加了。

  3. 當發生NSManagedObjectContextDidSaveNotification通知時,請確保您正在主線程上處理它。如果不是,則將消息轉發到主線程上的self。 (有關示例,請參閱Apple的示例代碼TopSongs)。

  4. 在主線程上處理NSManagedObjectContextDidSaveNotification時,請致電[context mergeChangesFromContextDidSaveNotification:notification]

  5. 你的NSFetchedResultsController將發送適當的協議消息給它的委託,所以你可以更新你的用戶界面。

  6. 如果您需要任何其他方式您的應用程序,通知的對象,你可以發佈你的對象可以觀察到,做任何他們需要做一個應用程序特定的通知。

你應該從您的NSOperation傳遞對象ID回主線程,並重新插入上下文。你已經在NSOperation中做到了。如果您需要知道主線程上的新對象標識可以通過並使用它們,但對象已被插入並保存到您的上下文中。

+0

Hi XJones。這是我目前的保存方法http://pastie.org/1791643 – 2011-04-13 16:06:36

+0

只是想我會補充說,操作中保存的對象確實出現在我已經NSLog'd的數組中。 – 2011-04-13 16:12:00

+0

+1不通過ObjectId的回 – Damien 2011-04-13 16:12:31

0

一件事來檢查:直到對象被保存到店

ManagedObjectIDs只是暫時的ID。因此,如果您在保存對象之前取得新創建的對象的ID並將其交給另一個線程/操作,那麼它將只有一個臨時ID,當對象實際上由任何線程/操作保存時它將會改變。

我不知道從閱讀說明書,但它可能是你正在努力尋找一個臨時的ID不再有效的對象。

+0

感謝您的回覆。我認爲這可能是問題,所以我把一個BOOL來檢查objectID是否是臨時ID,但它是否返回永久ID。 – 2011-04-14 10:26:49