2015-09-15 48 views
0

這是一個示例應用程序應用程序,我創建它來模仿我正在處理的案例。這是在我的視圖控制器使用CoreData和雨燕2.0和Xcode 7 BETA4處理親子子程序的應用程序崩潰managedObjectContexts

那麼單一視圖的應用程序創建一個privateObjectContext是的mainManagedObjectContext

let mainMOC = AppDelegate().managedObjectContext 
var privateObjectContext : NSManagedObjectContext? 

override func viewDidLoad() { 
    super.viewDidLoad() 
    // Do any additional setup after loading the view, typically from a nib. 

    privateObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType) 
    privateObjectContext?.parentContext = mainMOC 
} 

一個孩子,我知道保存在孩子MOC將它同步到父級,然後保存父級將其保存到持久性存儲區,但每次保存主要MOC時我省去我的孩子MOC沒有意義並且使得子級MOC冗餘的目的。因此,在我的所有測試完成後,我保存我的父母MOC,並按照預期將其存儲在持久存儲中。

但是,當我模擬應用程序崩潰時(通過轉到任務管理器並強行終止應用程序),它不會存儲在持久性管理器中;它應該有,因爲這個

func applicationWillTerminate(application: UIApplication) { 
     // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 
     // Saves changes in the application's managed object context before the application terminates. 
     self.saveContext() 
    } 

func saveContext() { 
     if managedObjectContext.hasChanges { 
      do { 
       try managedObjectContext.save() 
      } catch { 
       // Replace this implementation with code to handle the error appropriately. 
       // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
       let nserror = error as NSError 
       NSLog("Unresolved error \(nserror), \(nserror.userInfo)") 
       abort() 
      } 
     } 
    } 

managedObjectContext.hasChanges返回false,儘管在商務部的生命週期中具有的ViewController 上午我改變它錯了地方?

--edit 我使用一個擴展的NSManagedObjectContext批量創建測試對象

privateObjectContext?.performBlock { 
      self.privateObjectContext?.createTestObjects(100) { 
       (person: Person, index) in 
       person.name = "Test Person \(index)" 
      } 
      do { 
       try self.privateObjectContext?.save() 
      } catch { 
       print(error) 
      } 

     } 

在此之後,如果我從我的主要MOC取然後我得到預期100條記錄。

print(mainMOC.hasChanges) //true 
let persons = mainMOC.fetchAll(Person) 
print(persons.count) //100 

但強行崩潰應用程序後主MOC仍然沒有顯示任何變化。

+0

什麼是使用童工情況下,你的情況動機節「異步拯救」?你看到任何併發使用? – Shripada

+1

我有很多數據需要在我的主應用程序中定期保存在後臺。所以看着通過一個孩子MOC異步保存到MOC的選項,然後當用戶完成任務將其存儲在持久存儲中時。當應用程序在任務之間崩潰時,我必須處理該案例,因此問題 – firecast

+1

理想情況下,如果您打算立即將更新寫回到磁盤,則保存父級應立即在子級上下文中保存。 – Shripada

回答

2

應用程序將終止方法基本上從來沒有使用過,所以你不應該依賴它。你也不應該編碼來保存崩潰,首先你的應用不應該崩潰,其次很難知道哪些數據在崩潰時無效,所以你可能會破壞其他好數據。

一般而言,您應該立即保存或批量保存到持久性存儲。

請注意,您還可以構造不同的託管對象上下文,以便處理和保存事件,然後合併到主要上下文中。如果在保存時實際發現用戶界面存在問題,則可能只想進行此項工作。


嚴格爲您的問題,問題是,你沒有保存孩子MOC(至少不是在我們可以看到的代碼中)。所以,當你來保存主MOC時,它還沒有任何孩子的變化,沒有什麼可以保存的。

+0

我正在考慮的情況是由於某種原因應用程序崩潰的最壞情況。我肯定會不時地向持續協調員保存數據。 但是,當我殺死它時,調用'applicationWillTerminate'方法,但MOC沒有顯示任何更改。這是爲什麼? – firecast

+0

嗨,我已編輯我的代碼,以顯示測試案例,我保存我的孩子MOC,它確實得到反映在主MOC,因爲它應該但不顯示ApllicationWillTerminate方法中的更改。 NSManagedObjectContext是一個類,所以應該引用正確或可能我在這裏丟失的東西與他的生命週期 – firecast

1

如果您有大量的保存需要完成,並且正如@Wain正確指出的那樣,在終止時執行保存並不是一個好主意,但還有一種更好的方法可以在不扼住主線程的情況下執行此操作。您將需要創建與商店協調員關聯並在非主隊列中運行的根上下文。你的主要環境可以是這個環境的孩子。

參考在

https://www.cocoanetics.com/2012/07/multi-context-coredata/

+0

我可以看看這個。謝謝!!雖然我仍然不明白爲什麼主要的MOC在保存我的孩子MOC – firecast

+0

後顯示沒有變化好,是否有可能看看你的實際代碼? – Shripada