2012-08-03 74 views
5

在我的應用程序中,我有一個「主」NSPrivateQueueConcurrencyType上下文,作爲視圖控制器依賴和傳遞的上下文的父級。我想這樣做是爲了利用異步保存(此應用程序將iCloud與Core Data配合使用,並節省了大量輸出無處不在日誌的工作)。設置類似於在this article緩慢刪除並保存在嵌套NSManagedObjectContext

的底部所提及的Zarra方法在應用程序中保存通常是這樣的:

[context save:nil]; 
[context.parentContext performBlock:^{ 
    [context.parentContext save:nil]; 
}]; 

這似乎非常適用於小型編輯/更新工作,但我感到困惑我刪除多個對象時看到的內容(例如,刪除一個具有與其相關的數百個任務對象的項目)。

在這種情況下,保存是異步的,但它看起來像主線程進入信號量等待狀態(如我暫停調試器時所看到的)並且被有效阻止(我無法在UI中滾動)私有上下文完成保存。

實際上,我剛剛注意到,儘管存在這種異步保存模式,但單個對象的輕掃刪除刪除操作會導致明顯的延遲,因此應用中的所有刪除操作都很慢。

如果或者我分配了一個新的NSPrivateQueueConcurrencyType上下文,請將其持久存儲協調器設置爲AppDelegate中的主PSC並執行刪除並保存,但它仍執行大量工作,但UI永遠不會被阻止(但那麼我不得不擔心協調的背景下,在主要情況下重新考慮)。

任何想法我可能做錯了,或者你看到過這種行爲嗎?

回答

8

刪除可能需要很長時間。他們必須修復所有的關係。在進行大量刪除時,您應該做幾件事情。

首先,爲什麼你的UI在後臺刪除時發生阻塞?由於該後臺線程真的忙於執行刪除塊,並且您的用戶界面正試圖在刪除正在進行時更新數據。

運行實際工作的線程由一個FIFO隊列管理,所以如果給它一個很大的任務來執行,它將不能執行其他任務,直到長時間運行完成。

您可能正在使用FRC,並且它在嘗試在對象和關係發生更改時獲取更新。

如果你有一個很大的刪除,你可能想要改變你的提取,所以它只會查看當前MOC的數據,而刪除正在發生。刪除完成後,您可以通知提取請求返回查詢到商店本身。

此外,刪除大量內容時,最好在autorelease池內部的小塊中,在單獨的線程中進行。在該後臺線程中,一次刪除小塊,然後使用performBlockAndWait。這樣,您就不會用刪除請求加載工作線程的隊列,並且您的UI線程可以處理其請求。更快速。

或者,您還可以使用GCD的高級功能來創建高優先級和低優先級的隊列,用於將工作饋送給工作線程。您可以將寫入放在低優先級隊列上,並在高優先級隊列上進行讀取。

+0

謝謝Jody!我一直都遇到你有用的答案。我正在做更多的工作來研究我的問題。在一個屏幕上,我展示了我的項目(項目有許多任務),並且不使用NSFRC。我正在研究你爲我的另一個屏幕(它列出了任務並使用NSFRC)提到的事情,其中​​使用嵌套方法輕鬆刪除單個任務的速度很慢(如果我恢復到標準,則速度很快NSMainQueueConcurrencyType上下文綁定到PSC) – azsromej 2012-08-04 20:59:08

+0

在儀器中運行它。這是查看到底發生了什麼的最好方法。 – 2012-08-04 21:12:14

+0

奇怪的是,使用滑動刪除會導致阻止UI的保存,但使用Edit-Done按鈕(點擊紅色圓圈然後刪除)不會阻止,儘管流過commitEditingStyle:forRowAtIndexPath(其中deleteObject:並保存:發生) – azsromej 2012-08-05 17:49:06