2009-10-12 75 views
35

我使用Apple的CoreDataBooks示例應用程序作爲在後臺將數據拉入輔助管理對象上下文的基礎,然後將該數據合併到主管理對象中上下文。非法嘗試在不同的上下文中建立對象之間的關係'xyz'

我拉入的數據是一個Book實體,與實體(稱爲「所有者」)具有一對一的關係。 Owner實體與Book(稱爲「書籍」)具有多對多關係。

我的數據的形式爲XML文檔:

<Owner> 
    <Name>alexpreynolds</Name> 
    <ID>123456</ID> 
</Owner> 
<Books> 
    <Book>Book One</Book> 
    <Book>Book Two</Book> 
    ... 
    <Book>Book N</Book> 
</Books> 

Book One通過Book N與一個Owner"alexpreynolds, 123456")相關聯。

我把它解析成一個Owner實例和一個NSMutableSetBook實例組成。

當我第一次嘗試保存時,它可以很好地保存並且合併的數據在表格視圖中顯示。

但是,在第二次保存時,如果XML內容包含新書,則不起作用。

這裏發生了什麼:

我然後嘗試包含新Book XML文檔中加載的主要管理對象上下文尚未。新的Book正在使用與其他Book相同的Owner

我有挑選出這種獨特的Owner管理對象例程(我已經在我的主要管理對象上下文)和獨特的Book在主MOC找到。

由此,我在輔助MOC中創建了一個新的Book對象,並將其「owner」關係設置爲指向我在主要MOC中找到的唯一Owner對象。

當我保存,我得到以下錯誤:

*** Terminating app due to uncaught 
exception 'NSInvalidArgumentException', 
reason: 'Illegal attempt to establish a 
relationship 'owner' between objects in 
different contexts 

(source = <Book: 0x7803590> 
(entity: Book; id: 0x7802ae0 <x-coredata:/// 
Book/t527F06B2-3EB5-47CF-9A29-985B0D3758862> 
; data: { 
creationDate = 2009-10-12 06:01:53 -0700; 
name = nil; 
nameInitial = nil; 
operations = (
); 
owner = nil; 
type = 0; 
}) , 

destination = <Owner: 0x78020a0> (entity: 
Owner; id: 0x3a56f80 <x-coredata://043AF2F0-1AD0- 
4078-A5E8-E9D7071D67D1/Owner/p1> ; data: { 
books = "<relationship fault: 0x7801bf0 'books'>"; 
displayName = alexpreynolds; 
ownerID = 123456; 
}))' 

如何在二級MOC創建一個新的Book實體,這樣我仍然可以將其與在主預先存在Owner關聯MOC?

回答

63

不能在不同的託管對象上下文中的對象之間建立關係。所以解決這個問題的一種方法是將對象引入托管對象上下文中。

例如:

NSManagedObject *book = // get a book in one MOC 
NSManagedObject *owner = // get an owner in a different MOC 
[[owner mutableSetValueForKey:@"books"] addObject:[owner.managedObjectContext objectWithID:[book objectID]]]; 

你做那麼什麼是真正獲取的Book到相同的管理對象上下文與owner。請記住,只有在book已被保存的情況下才有可能。託管對象上下文將在持久性存儲中查找對象,因此必須先保存該對象。

+0

感謝您的支持!我正在Core Data中使用後臺GCD線程,所以必須有一個NSManagedObject的背景,我忘記了用它來插入父對象,因此它使用的是主線程NSManagedObject!不管怎樣,謝謝! :) – runmad 2011-09-25 20:38:22

1

正如錯誤所述,您不允許在一個核心數據對象中存在關係,該對象的值設置爲保存在另一個上下文中的另一個對象。解決此問題的一種方法是等到保存新對象並將其合併回主要上下文後,然後將owner關係設置爲合適(因爲兩個對象現在都處於相同的上下文中,所以沒有問題) 。

+0

遵循核心數據手冊示例,在合併發生後釋放輔助MOC。如果我將輔助MOC作爲實例變量,則主要MOC的所有者指的是輔助MOC中的書籍,它會給出錯誤消息。如果我有一個次要的MOC所有者來引用次要MOC中的書籍,那麼當我合併時,我現在擁有重複的所有者實例,這是不正確的。理想情況下,我可以與現有的所有者聯繫。如果你有時間,你能否詳細解釋一下你的答案? – 2009-10-13 11:05:53

8

我有同樣的問題,這句話幫助我解決了錯誤。

You can't have relationships between objects in different managed object contexts. So one way of getting around that is to bring the object into the managed object context.

這裏是我的代碼(我更換了變數,使其爲你工作):

// Have the owner object and get the managedObjectContext 
Owner *owner = [[DataFunctions alloc] getCurrentOwner]; 
NSManagedObjectContext *context = [owner managedObjectContext]; 

// Create a book and use the manageObjectContext of owner 
Book *book = [NSEntityDescription insertNewObjectForEntityForName:@"Book" inManagedObjectContext:context]; 
[newQuote setValue: "Book Title" forKey:@"title"]; 
[newQuote setOwner:owner]; 

我希望這有助於:)

0
book *book = [mainContext ........] //Get book from default context 

NSManagedObjectID *objectId = [book objectID]; 

Book *tmpBook = [tmpContext objectWithID:objectId]; //Now book has the legal relationship 
3

在這裏,你正在試圖建立用不同的上下文獲取/創建的兩個對象之間的關係。核心數據不會讓你建立這種關係。爲了達到這個目的,你應該使用objectID獲取第一個對象的上下文(你試圖建立關係)。現在你應該能夠建立這兩個對象之間的關係。例如:

MagicalRecord.saveWithBlock({[unowned self] (localContext: NSManagedObjectContext!) in 

    let user = User.MR_createEntityInContext(localContext)! 
    ..... 
    ..... 
}) //here local context stores data on end of block itself 

MagicalRecord.saveWithBlock({[unowned self] (localContext: NSManagedObjectContext!) in 

    let address = Address.MR_createEntityInContext(localContext)! 
    ..... 
    ..... 
    let user = localContext.objectWithID(self.user!.objectID) as! User 
    user.address = address 
}) 

希望這會幫助你!

相關問題