2

我有一個操作對象,它創建它自己的管理對象上下文。當主線程集中在UI方面時,操作對象基本上執行計算以從主線程卸載負載。該操作對象的MOC在整個應用程序中共享一個公共持久存儲。獨立ManagedObjectContext中的Coredata對象錯誤與持久存儲中的更改

有時會發生這樣的情況,即在執行操作時,主線程的MOC會收到後端變化的通知。因此,我嘗試合併MOC的更改,其中可能會發生模型對象中的某些刪除。在一些罕見的情況下,正如我所觀察到的,操作對象可能還沒有實現,並且它們處於故障狀態,同時主線程將更改存儲到MOC(並持久存儲)中。我的應用在這種情況下崩潰了。

根據標準文本,我有一個專用於我的線程的MOC,根據我的理解,故障的數據應該從線程的MOC中訪問。當從線程的MOC訪問故障請求時,它是否有所不同,比如說,同一個對象可能已從商店中刪除?

請參閱該堆棧跟蹤: enter image description here

什麼是處理這個更好的辦法?

我的確從這篇文章瞭解到:https://stackoverflow.com/a/5722914/260665線程的託管對象上下文沒有意識到存儲的底層變化,並且故障對象預計存在於存儲中。因此,最好這將是兩種:

  1. 更新的時候有使用NSManagedObjectContextDidSaveNotification通知(來源:https://stackoverflow.com/a/5722914/260665)在店內任何潛在的變化(刪除)該線程對象的集合

  2. 檢查在店裏是否存在NSManagedObject的紀錄試圖通過在MOC(來源:https://stackoverflow.com/a/14297708/260665)使用-existingObjectWithID來訪問它的屬性之前,代碼

  3. 處理異常? (不得已,來自:https://stackoverflow.com/a/15361906/260665

我不可能與解決方案前進1 & 2這不是NSManagedObject的屬性直接我訪問,我有NSFetchedResultController具有某種描述符中該應用程序崩潰:

-(NSMutableArray*)fetchedTaskObjects 
{ 
    if (nil==fetchedTaskObjects_ && self.taskLocalFetchedResultsController && self.persistantTaskFetchedResultsController) 
    { 
     NSArray *allNonPersistantTasks = [self.taskLocalFetchedResultsController fetchedObjects]; 
     NSArray *allPersistantTasks = [self.persistantTaskFetchedResultsController fetchedObjects]; 

     fetchedTaskObjects_ = [[NSMutableArray alloc] init]; 
     [fetchedTaskObjects_ addObjectsFromArray:allNonPersistantTasks]; 
     [fetchedTaskObjects_ addObjectsFromArray:allPersistantTasks]; 
     NSSortDescriptor *tasksSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.mockTaskCounter" 
                       ascending:YES]; 
     NSSortDescriptor *shortTextSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.shortText" 
                        ascending:YES]; 
     NSSortDescriptor *headerTextSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.accountAssignmentText" 
                        ascending:YES]; 
     [fetchedTaskObjects_ sortUsingDescriptors:[NSArray arrayWithObjects:tasksSortDescriptor, shortTextSortDescriptor, headerTextSortDescriptor, nil]]; 
    } 
    return fetchedTaskObjects_; 
} 

因此,以正確的方式找到解決方案的任何建議?

編輯: 我正的錯誤(例外):

CoreData could not fulfill a fault for '0x2b0298a0 <x-coredata://E7E91AFC-5BE6-4996-B28F-92CD115A5D0A/CSTaskRegister/p14746>' 

哪一行崩潰?

它在任何一個排序描述符中崩潰,其中受排序的Managed對象的內部屬性試圖通過排序描述符訪問以進行排序。由於它是一個線程,因此我們不確定在商店中何時刪除底層對象。所以,線程崩潰有時也會出現在我的統計計算代碼中。

爲什麼要合併兩個FRC的結果?

因爲該項目最初是以這兩種情況下的不同MOC開始的,現在儘管MOC是單一的,但分化仍然存在。但是我認爲具有獨立FRC的目的不是問題。

+0

「fetchedTaskObjects」的哪一行是你的應用程序崩潰?什麼是錯誤? 你爲什麼要結合兩個'NSFetchedResultsController'中的'fetchedObjects'? –

+0

更新了問題並回答了您的查詢。然而,我最終選擇了使用異常處理的第三種解決方案,並忽略了這些操作的結果。 –

回答

1

做了足夠的研究,避免這種情況發生的唯一方法是通過聽取通知(問題中提到的第一個解決方案)來更新集合,另一種方法是在訪問之前仔細檢查-existingObjectWithID(第二個解決方案)屬性。

但在我的情況下,刪除(來自持久性存儲)託管對象的屬性由排序描述符在內部訪問。讓我別無選擇,只能在線程中處理異常(第三個解決方案),忽略此線程的(錯誤)結果。

1

如果不能合併或不想觸摸操作MOC - 例如,因爲它正在使用中,你需要保證操作數據更新成爲系列化

的想法是,操作運行它假定其當前數據狀態的視圖是恆定,因此必須不能改變時。

您有幾種選擇來保證這一點:

如果操作運行,和你有一個更新請求,並希望立即更新的數據,包括共享的持久性存儲,則需要先取消操作並等待操作完成(操作MOC後不再發生訪問)。然後開始更新主MOC中的數據。更新完成後,包括持久性存儲在內,您可以重新啓動該操作,然後新初始化正確合併 MOC - 反映數據的實際狀態。

同樣,您可以推遲更新請求,直到運行操作完成。

+0

需要注意,好建議。我可以推遲主MOC的更新請求或取消操作並等待完成。你能否給我們添加一個關於爲什麼在可可中不喜歡異常處理的參考,並且應用程序應該在異常情況下退出到這個答案中,以便將來可以作爲其他人的參考。 –

相關問題