我有一個問題,我一直在努力幾個星期doozey。它涉及每當我保存Core Data託管對象上下文時出現口吃UI性能。我已經盡我所能,並且正在尋求一些幫助。背景託管對象上下文交錯UI動畫
現狀
我的應用程序使用兩個NSManagedObjectContext
實例。一個屬於應用程序委託並具有附加的持久性存儲協調器。另一個是主要MOC的一個孩子,屬於一個Class
對象,稱爲PhotoFetcher
。它使用NSPrivateQueueConcurrencyType
,因此在此MOC上執行的所有操作均發生在後臺隊列中。
我們的應用程序從我們的API下載表示關於照片數據的JSON數據。爲了檢索從我們的API的數據,以下步驟順序進行:
- 構造一個
NSURLRequest
對象,並使用NSURLConnectionDataDelegate
協議來構造從請求返回的數據,或處理錯誤。 - 一旦JSON數據的下載完成,執行,做以下次級MOC的隊列塊:
- 解析使用
NSJSONSerialization
爲基礎類實例的JSON。 - 迭代解析的數據,根據需要在我的後臺上下文中插入或更新實體。通常,這導致大約300個新的或更新的實體。
- 保存背景上下文。這將我的更改傳播到主要的MOC。
- 在主MOC上執行一個塊以節省它的上下文。這是爲了讓我們的數據保存到磁盤,一個
SQLite
商店。最後,對委託進行回調,通知他們已將響應完全插入到Core Data存儲中。
- 解析使用
的代碼保存背景MOC看起來是這樣的:
[AppDelegate.managedObjectContext performBlock:^{
[AppDelegate saveContext]; //A standard save: call to the main MOC
}];
當主對象上下文保存,它也節省了自上次已經下載了相當數量的JPEG文件發生主對象上下文保存時。目前,在iPhone 4上,我們正在下載70個壓縮率爲70%的15張200x200 JPEG,或總共大約2MB的數據。
問題
這個工作,運作良好。我的問題是,一旦背景上下文保存,運行在我的視圖控制器中的NSFetchedResultsController
就會獲取傳播到主MOC的更改。它在我們的PSTCollectionView
插入新的單元格,這是一個開源的克隆UICollectionView
。在插入新單元格時,主要上下文會保存並將這些更改寫入磁盤。這可以在運行iOS 5.1的iPhone 4上,從250-350毫秒的任何地方。
在三分之一秒內,該應用程序完全沒有響應。在保存之前正在進行的動畫暫停,並且在保存完成之前沒有新的用戶事件發送到主運行循環。
我使用時間探查,以確定是什麼阻止了我們的主線程運行我們的應用程序在儀器。不幸的是,結果相當不透明。這是我從儀器獲得的最重的堆棧軌跡。
它出現要保存更新持久存儲,但我也不能肯定。所以我刪除了任何對saveContext
的調用,因此MOC不會觸及磁盤,並且主線程上的阻塞調用仍然存在。
跟蹤,以文本的形式,看起來像這樣:
Symbol Name
-[NSManagedObjectContext(_NestedContextSupport) _parentObjectsForFetchRequest:inContext:error:]
-[NSManagedObjectContext executeFetchRequest:error:]
-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]
_perform
_dispatch_barrier_sync_f_invoke
_dispatch_client_callout
__82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke_0
-[NSManagedObjectContext(_NestedContextSupport) _parentObjectsForFetchRequest:inContext:error:]
-[NSManagedObjectContext executeFetchRequest:error:]
-[NSPersistentStoreCoordinator executeRequest:withContext:error:]
-[NSSQLCore executeRequest:withContext:error:]
-[NSSQLCore objectsForFetchRequest:inContext:]
-[NSSQLCore newRowsForFetchPlan:]
-[NSSQLCore _newRowsForFetchPlan:selectedBy:withArgument:]
-[NSSQLiteConnection execute]
我曾嘗試
之前我們接觸核心數據的代碼,我們做的第一件事就是優化我們的JPEG文件。我們切換到較小的JPEG,並看到性能提升。然後,我們減少了我們一次下載的JPEG數量(從90減少到15)。這也導致了顯着的性能提升。但是,我們仍然在主線程上看到250-350ms長的塊。
我想的第一件事就是剛剛擺脫背景MOC的消除,這可能會導致問題的可能性。事實上,它讓事情變得更糟,因爲我們的更新或創建代碼在主線程上運行,導致整體動畫性能下降。
改變持久店NSInMemoryStoreType
沒有效果。
任何人都可以點我的「祕密武器」,這將使我這樣的背景下被管理對象上下文已承諾的UI表現?
看起來你正在保存的對象然後在主線程中出現故障。你能運行核心數據分析器來查看導致錯誤的原因嗎?你有沒有使用反向關係? – ndfred
我會檢查出CD檢查員,但我確實使用inver關係。 –