我在主线程中创建实体Artist, 然后在后台线程中传递它并与实体相册相关联。
如何正确完成?
- (IBAction)add:(id)sender
{
Artist *artist = [Artist MR_createEntity];
artist.title = @"Eminem";
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
// here a large calculation
Album *album = [Album MR_createEntity];
album.title = @"Album 1";
[artist setAlbums:[NSSet setWithArray:@[album]]];
dispatch_async(dispatch_get_main_queue(),^{
[artist.managedObjectContext MR_saveToPersistentStoreAndWait];
});
});
}
错误:
MagicalRecordTest[2008:1803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Illegal attempt to establish a relationship 'albums' between objects in different contexts (source = <Artist: 0x15eaa2d0>
答案 0 :(得分:5)
您违反了核心数据的主要规则之一。只能在创建它们的线程上访问NSManagedObjectContext
及其关联的NSManagedObject
实例。您可以传递NSManagedObjectID
个实例,但不能传递NSManagedObject
个实例。
此外,当您在两个NSManagedObject
实例之间创建关系时;两个实例必须来自同一个NSManagedObjectContext
,否则您将收到上述错误。
取代上面的方法,重新获取块中的Artist
。我可以提供有关如何使用Core Data执行此操作的示例代码,但您需要研究如何使用MagicalRecord执行此操作。
答案 1 :(得分:3)
Marcus是正确的,因为您需要了解您正在使用的上下文,并且只需要在单个队列或线程中使用它们。 MagicalRecord有一个很好的API来管理它。在你的情况下,你应该做更多的事情:
- (void) add;
{
NSManagedObjectContext *mainContext = [NSManagedObjectContext MR_defaultContext];
Artist *artist = [Artist MR_createInContext:mainContext];
[mainContext MR_saveToPersistentStoreAndWait];
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
Artist *localArtist = [artist MR_inContext:localContext];
localArtist.title = @"Album...";
}];
}
MagicalRecord将设置保存队列并在正确的位置执行操作,只要您记住第一个,就不能在NSManagedOjbectContexts之间传输临时对象。其次,必须为每个线程/队列/块使用单独的上下文。在这种情况下,localContext是为您创建的,一旦块完成,MagicalRecord将尝试为您保存本地/临时上下文。