2012-08-16 20 views
27

我有兩個管理對象上下文設置這樣一個應用程序:核心數據:兒童上下文是否獲得新插入對象的永久對象ID?

  • 父上下文:NSPrivateQueueConcurrencyType,聯繫到持久性存儲。
  • 主要上下文:NSMainQueueConcurrencyType,父上下文的子項。

當插入一個新的管理對象主要方面,我省的主要方面,然後像這樣父上下文:

[context performBlockAndWait:^{ 
    NSError * error = nil; 
    if (![context save: &error]) { 
     NSLog(@"Core Data save error %@, %@", error, [error userInfo]); 
    } 
}]; 

[parentContext performBlock:^{ 
    NSError *error = nil; 
    BOOL result = [parentContext save: &error]; 
    if (! result) { 
     NSLog(@"Core Data save error in parent context %@, %@", error, [error userInfo]); 
    } 
}]; 

我的理解是,當管理對象第一次創建,它有一個臨時的objectID。然後保存主要上下文,並使用其臨時ID獲取父對象。然後保存父上下文。保存最後一個上下文時,父上下文中的臨時objectID轉換爲永久objectID

所以:

  • 是否永久對象ID永遠都會自動回到 到主(子)進行上下文傳播?
  • 當我強迫與 [NSManagedObjectContext obtainPermanentIDsForObjects:error:],然後後臺應用程序,激活它,重載獲取對象的永久編號,可以使用主上下文的objectWithID:獲取對象和訪問屬性,我得到

    「CoreData可能沒有爲...做過錯「。

這種方法有什麼問題?

+0

Jorge:我得到一個CoreData不能在兒童上下文中獲取永久ID並保存ManagedObject時發生故障。你知道是什麼原因嗎?謝謝 – 2014-06-17 22:29:45

回答

40

這是一個已知的bug,很快就希望固定的,但在一般情況下,獲得一個永久的ID就足夠了,只要你做,你保存在第一胎中的數據之前,你只包括插入的對象:

[moc obtainPermanentIDsForObjects:moc.insertedObjects.allObjects error:&error] 

在一些複雜情況下,最好在創建實例後立即獲取永久ID,特別是在您有複雜關係時。

你打電話的時間和方式obtainPermanentIDsForObjects

我不關注應用程序崩潰的部分。也許更好的解釋會有所幫助。

+0

moc.insertedObjects中沒有設置。我想這在保存後會被清除? 我正在做的是在應用程序背景時保存用戶對文檔的選​​擇。該應用可以在後臺更新這些應用。當它進入前臺時,會重新創建上下文,並使用對象ID恢復選擇。但是,在進入後臺之前,即使在上下文保存之後,新創建的文檔也會有臨時ID。如果我強制獲取這些永久ID,當應用程序重新激活時,它不能重新創建託管對象。 – Jorge 2012-08-17 00:43:00

+1

是的,insertedObjects只保存已插入但未保存的對象。即使您給他們永久ID,他們仍然會保留在insertedObjects中,直到他們被保存。嘗試在保存之前在您的子上下文中進行獲取。它應該獲取ID,然後根據它們傳播保存。確保通過所有上下文完全保存到數據庫。 – 2012-08-17 00:53:47

+0

在保存之前獲取ID取得了訣竅。謝謝! – Jorge 2012-08-17 01:05:41

8

正如喬迪上面所說的,用一個孩子ManagedObjectContext必須通過執行以下強制永久ID的創建在後臺線程創建一個新的NSManagedObject時之前,您保存:

NSError *error = nil; 

[threadedMOC obtainPermanentIDsForObjects:threadedMOC.insertedObjects.allObjects error:&error]; 

BOOL success = [threadedMOC save:&error]; 

恕我直言,這不是這樣做非常直觀 - 畢竟,您在保存之前要求獲得永久ID!但這似乎是工作的方式。如果您在保存後詢問永久ID,那麼ID仍然是暫時的。從Apple文檔,你其實可以使用以下方法來確定對象的ID是暫時的:

BOOL isTemporary = [[managedObject objectID] isTemporaryID]; 
1

問題仍然在IOS存在於雨燕8.3解決方案:

func saveContext(context: NSManagedObjectContext?){ 
    NSOperationQueue.mainQueue().addOperationWithBlock(){ 
    if let moc = context { 
     var error : NSError? = nil 
     if !moc.obtainPermanentIDsForObjects(Array(moc.insertedObjects), error: &error){ 
      println("\(__FUNCTION__)\n \(error?.localizedDescription)\n \(error?.userInfo)") 
     } 
     if moc.hasChanges && !moc.save(&error){ 
      println("\(__FUNCTION__)\n \(error?.localizedDescription)\n \(error?.userInfo)") 
     } 
    } 
} 
} 

func saveBackgroundContext(){ 
    saveContext(self.defaultContext) 

    privateContext?.performBlock{ 
     var error : NSError? = nil 
     if let context = self.privateContext { 

      if context.hasChanges && !context.save(&error){ 
       println("\(__FUNCTION__)\n \(error?.localizedDescription)\n \(error?.userInfo)") 
      }else { 
       println("saved private context to disk") 
      } 
     } 
    } 
} 

其中:

  • defaultContext has concurrencyType .MainQueueConcurrencyType
  • privateContext has concurrencyType .PrivateQueueConcurrencyType
相關問題