从子上下文分配对象时非法尝试建立关系
Posted
技术标签:
【中文标题】从子上下文分配对象时非法尝试建立关系【英文标题】:Illegal attempt to establish a relationship when assigning object from child context 【发布时间】:2014-06-22 07:19:53 【问题描述】:我花了几个小时试图解决父子核心数据模型的问题。但是,让我们从头开始。我有主要上下文和以.parentContext
作为主要上下文的子上下文。
- (NSManagedObjectContext *)mainContext
if (!_mainContext)
_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
return _mainContext;
- (NSManagedObjectContext *)childContext
if (!_childContext)
_childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_childContext setParentContext:self.mainContext];
return _childContext;
接下来我在不同的上下文中创建两个对象。
Entity2 *entity2 = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([Entity2 class])
inManagedObjectContext:_stack.childContext];
Entity1 *entity1 = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([Entity1 class])
inManagedObjectContext:_stack.mainContext];
entity1.arg1 = @"ABC";
entity1.arg2 = @"DEF";
这里一切正常。
然后我想将一个对象添加到另一个对象的关系中,无论我尝试将entity1
添加到entity2
还是反之亦然。
[entity1 setEntity2:entity2];
在Multi-Context Core Data | Cocoanetics 的文章中,我读到我应该使用保存操作执行块,因为对象彼此不认识。所以它看起来像这样:
[_stack.childContext performBlock:^
NSError *error;
if (![_stack.childContext save:&error])
NSLog(@"Error: %@", error);
[_stack.mainContext performBlock:^
NSError *error;
if (![_stack.mainContext save:&error])
NSLog(@"Error: %@", error);
[entity1 setEntity2:entity2];
];
];
但是无论我把[entity1 setEntity2:entity2]
放在哪里,它都以:
2014-06-22 08:48:24.444 MultiContextualCoreData[1324:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Illegal attempt to establish a relationship 'entity1' between objects in different contexts (source = <Entity2: 0x8c81570> (entity: Entity2; id: 0x8c80000 <x-coredata:///Entity2/tC31696AE-0A0A-424E-9C8E-1E19085F3FB43> ; data:
entity1 = nil;
) , destination = <Entity1: 0x8c80200> (entity: Entity1; id: 0x8c80250 <x-coredata:///Entity1/tC31696AE-0A0A-424E-9C8E-1E19085F3FB42> ; data:
arg1 = ABC;
arg2 = DEF;
entity2 = nil;
))'
*** First throw call stack:
(
0 CoreFoundation 0x01b541e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x018d38e5 objc_exception_throw + 44
2 CoreData 0x00293b7e _PFManagedObject_coerceValueForKeyWithDescription + 3614
3 CoreData 0x002614e9 _sharedIMPL_setvfk_core + 185
4 CoreData 0x0027ada7 _svfk_0 + 39
5 MultiContextualCoreData 0x00002d4a -[AppDelegate test] + 554
6 MultiContextualCoreData 0x00002acd -[AppDelegate application:didFinishLaunchingWithOptions:] + 605
7 UIKit 0x0058d14f -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 309
8 UIKit 0x0058daa1 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1810
9 UIKit 0x00592667 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 824
10 UIKit 0x005a6f92 -[UIApplication handleEvent:withNewEvent:] + 3517
11 UIKit 0x005a7555 -[UIApplication sendEvent:] + 85
12 UIKit 0x00594250 _UIApplicationHandleEvent + 683
13 GraphicsServices 0x03a07f02 _PurpleEventCallback + 776
14 GraphicsServices 0x03a07a0d PurpleEventCallback + 46
15 CoreFoundation 0x01acfca5 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
16 CoreFoundation 0x01acf9db __CFRunLoopDoSource1 + 523
17 CoreFoundation 0x01afa68c __CFRunLoopRun + 2156
18 CoreFoundation 0x01af99d3 CFRunLoopRunSpecific + 467
19 CoreFoundation 0x01af97eb CFRunLoopRunInMode + 123
20 UIKit 0x00591d9c -[UIApplication _run] + 840
21 UIKit 0x00593f9b UIApplicationMain + 1225
22 MultiContextualCoreData 0x00002efd main + 141
23 libdyld.dylib 0x0219b701 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
我在这里做错了什么?
提前感谢您的帮助。
【问题讨论】:
【参考方案1】:问题是两个对象必须属于同一个上下文才能在它们之间建立关系。在您的情况下,其中一个上下文具有私有类型,它有自己的队列可以工作,主上下文在主队列上工作。这是一种防止您在未来遇到并发问题的方法。
可能的解决方案是
创建entity1
,保存主上下文,使用managedObjectID
在子上下文中检索它,或者如果更有意义,则使用获取请求,然后只有当你有entity1
和entity2
时才建立关系相同的上下文
或者,简单地说,如果您的逻辑允许,则在同一上下文中创建两个对象。
【讨论】:
谢谢,这对我很有帮助。我使用第一种情况(使用NSManagedObjectID
获取对象,因为我无法在同一上下文中创建这些对象。
我使用属性注入在同一上下文(选项 2)中创建了两个对象,并解决了问题,谢谢
@Naishta 你能举一些例子,你是如何在相同的上下文中创建对象的吗?以上是关于从子上下文分配对象时非法尝试建立关系的主要内容,如果未能解决你的问题,请参考以下文章
NSInvalidArgumentException:非法尝试在不同上下文中的对象之间建立关系
单一上下文但“非法尝试在不同上下文中的对象之间建立关系‘xyz’