Незаконная попытка установить связь «xyz» между объектами в разных контекстах.
-
20-09-2019 - |
Вопрос
Я использую Apple CoreDataBooks
пример приложения в качестве основы для извлечения данных во вторичный контекст управляемого объекта в фоновом режиме, а затем слияния этих данных с первичным контекстом управляемого объекта.
Данные, которые я извлекаю, представляют собой Book
сущность с отношением «к-одному» с Owner
сущность (называемая «владельцем»).А 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
экземпляр и NSMutableSet
состоит из Book
экземпляры.
Когда я пытаюсь сохранить в первый раз, все сохраняется нормально, и объединенные данные отображаются в виде таблицы.
Однако при втором сохранении, когда содержимое XML содержит новую книгу, это не работает.
Вот что происходит:
Затем я пытаюсь загрузить XML-документ, содержащий новый Book
еще не в контексте основного управляемого объекта.Новый Book
использует тот же самый Owner
как то, что связано с другим Book
с.
У меня есть процедуры, которые выделяют это уникальное Owner
управляемый объект (который у меня уже есть в контексте основного управляемого объекта) и уникальный Book
то есть нет найден в первичном MOC.
Из этого я создаю новый Book
объект во вторичном MOC, и я установил его "owner
"отношения, указывающие на уникальность 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;
}))'
Как мне создать новый Book
объект во вторичном MOC, чтобы я мог связать его с ранее существовавшим Owner
в первичном МОК?
Решение
Вы не можете иметь отношения между объектами в разных контекстах управляемых объектов.Один из способов обойти это — поместить объект в контекст управляемого объекта.
Например:
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
уже сохранен.Контекст управляемого объекта будет искать объект в постоянном хранилище, поэтому его необходимо сначала сохранить.
Другие советы
У меня была такая же проблема, и это предложение помогло мне исправить ошибку.
Вы не можете иметь отношения между объектами в различных контекстах управляемых объектов.Таким образом, один из способов обойти это - привести объект в контекст управляемого объекта.
Вот мой код (я заменил переменные, чтобы он работал у вас):
// 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];
Надеюсь, это поможет :)
Здесь вы пытаетесь установить связь между двумя объектами, которые извлекаются/создаются в другом контексте.Базовые данные не позволят вам установить такие связи.Для этого вам следует получить второй объект (с которым вы пытаетесь установить связь) с контекстом первого объекта с 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
})
Надеюсь, что это поможет вам!
Как говорится в ошибке, вам не разрешено иметь связь в одном объекте Core Data, значение которого установлено на другой объект, находящийся в другом контексте.Один из способов обойти это — подождать, пока вы сохраните новый объект и объедините его обратно с основным контекстом, а затем установите owner
соответствующие отношения (поскольку оба объекта теперь находятся в одном и том же контексте, с этим проблем нет).
book *book = [mainContext ........] //Get book from default context
NSManagedObjectID *objectId = [book objectID];
Book *tmpBook = [tmpContext objectWithID:objectId]; //Now book has the legal relationship
Быстрая версия...
context.insert(objectFromOtherContext)