2010-07-19 76 views
7

我正在開發一個帶有核心數據的iPhone應用程序。所有用戶數據應與我們的服務器同步。爲此,我創建了NSOperation的子類,從我們的Web服務加載新數據並創建相應的託管對象。爲了維護它們之間的關係,每個對象都使用remoteID(它是關係服務器DB的主鍵)進行傳輸。核心數據executeFetchRequest拋出NSGenericException(集合在枚舉時發生了變化)

假設有兩個管理對象:部門< - >>員工。同步工作如下:

  1. 從服務器加載所有部門。對於每個部門:創建一個Department對象並設置其RemoteID。

  2. 從服務器加載所有員工。對於每個員工:創建員工對象,獲取相關部門(通過remoteID)並將其分配給員工。

抓取一個部門導致了以下異常:

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x69c8a10> was mutated while being enumerated.<CFBasicHash 0x69c8a10 [0x2d6d380]>{type = mutable set, count = 1424, 
entries => <A list of all newly created entities> 

*** Call stack at first throw: 
0 CoreFoundation 0x02d04919 __exceptionPreprocess + 185 
1 libobjc.A.dylib 0x02e525de objc_exception_throw + 47 
2 CoreFoundation 0x02d043d9 __NSFastEnumerationMutationHandler + 377 
3 CoreData  0x026225d0 -[NSManagedObjectContext executeFetchRequest:error:] + 4400 
4 myApp   0x00059de4 +[AppFactory departmentWithRemoteID:inManagedObjectContext:] + 259 

的不引發異常每一次。將代碼移到主線程可以解決問題。我不知道什麼是錯的。我在同步線程中創建了一個新的NSManagedObjectContaxt,並通過其NSManagedObjectID傳遞了所有託管對象。

有什麼想法?

回答

1

關閉我的頭頂:「同步」線程是否將新對象添加到Department集合,同時在主線程上迭代它?

通常,當您在枚舉集合的同時修改集合時,會發生此類異常。在多線程場景中,它也可能意味着您的集合在沒有正確線程同步的情況下同時枚舉和更新。

+0

對我來說這可能是這類問題的原因。什麼是解決這些問題的最佳方法,你有什麼想法@octy? – 2011-03-18 17:26:56

+0

Adeem,你的問題的一個很好的答案提供了一個鏈接的討論:http://stackoverflow.com/questions/3364769/iphone-nsfetchedresultscontroller-with-delegate-and-data-update-from-a-separate – octy 2011-03-22 18:45:48

4

錯誤「someCollection被枚舉時發生了變化」是由於枚舉器逐漸通過它而改變了一個可變集合,即數組,字典,集合等。由於您無法枚舉移動目標,因此會觸發錯誤。

在這種情況下,錯誤很可能是由於嘗試在主線程上枚舉Department的員工關係而導致的,用於顯示在桌面視圖中,而後臺線程同時將員工添加到關係中。

解決了這個問題,當你從後臺線程合併變更時,你必須凍結用戶界面。對於tableviews,在tableview控制器中正確實現委託方法的獲取結果控制器(NSFetchedResultsController)將很好地處理這個問題。

重要的是在合併新數據之前將beginUpdates發送到tableview。這將告訴表,它的基礎數據結構正在發生變化,所以它不會嘗試重繪本身。合併完成後,將endUpdates發送到tableview以使其顯示新信息。

+0

我認爲關於這種問題,因此我創建了兩個NSManagedObjectContexts(一個用於主線程,一個用於同步線程)。這不是一個有效的解決方案嗎?我也爲我的tableviews使用NSFetchedResultsController。 – Roland 2010-07-19 14:36:04

+0

是的,但是當合並上下文所做的更改時,它們會觸發更新以反映其他更改所做的更改。 FRC委託方法讓您告訴UI在處理這些更改時凍結。然後解凍UI並讓它顯示更新。這個過程通常對用戶是不可見的。 – TechZen 2010-07-19 14:52:40

+0

在將更改合併到主線程之前,應用程序崩潰。 – Roland 2010-07-19 14:52:56

13

我有同樣的問題... 它解決了,因爲我使用的是在後臺線程主線程上創建的managedObjectContext。 解決的辦法是在後臺線程上創建一個不同的ManagedObjectContext,然後使用常規的persistentStoreCoordinator ... 它在那之後很好地工作!

0

我有同樣的問題。您可以使用鎖定,解鎖接收器。我直到現在才解決了這個問題。

相關問題