【发布时间】:2014-02-17 12:16:53
【问题描述】:
我有一个多线程应用程序,我需要将私有上下文合并到主上下文,而主上下文又连接到持久存储控制器。
我还需要创建不受管理的临时对象(直到我后来决定管理它们)。
首先,我尝试如下创建我的临时对象;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:myMainQueueContext];
User* user = (User *)[[User alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
在决定是否保留该对象后,我就干脆了;
[privateContext insertObject:user];
在我将应用程序设为多线程之前,这很好用,但现在在稍微拆开东西并通过子/父上下文添加多线程并发之后,结果并不如预期。
通过查看上下文的“registeredObjects”,我可以看到我创建的并且现在插入的用户是在 privateContext 中管理的。保存后,mainContext 发生了相应的变化,我可以看到它 hasChanges 并且在 registeredObjects 中现在有一个对象。
但仔细观察 mainContext 中的注册对象,发现它已被清空。没有内容。根据类型,所有属性都是 nil 或 0。因此,人们会认为这可能是因为 objectId 不一样......但它是 ;( 它是同一个对象。但没有内容。
我试图在此处的另一篇文章中就这个问题获得一些意见,但没有成功。
Child context objects become empty after merge to parent/main context
不管怎样,我终于通过改变我创建对象的方式来完成工作;
User* user = [NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:privateContext];
突然间,我的子对象被合并到 mainContext 而不会丢失它们的内容,原因我不知道,但不幸的是,这也导致我不能再创建临时的非托管对象......;(我读到 Marcus在创建非托管对象时,Zarra 支持我的第一种方法,但这不适用于在我的多线程应用程序中合并上下文...
期待任何想法和想法——我是唯一一个尝试在异步工作线程中创建临时对象的人吗,我只想管理/合并其中的一部分到 mainContext?
编辑
具体代码显示什么是有效的,更重要的是什么是无效的;
//Creatre private context and lnk to main context..
NSManagedObjectContext* privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
//Link private context to main context...
privateManagedObjectContext.parentContext = self.modelManager.mainManagedObjectContext;
[privateManagedObjectContext performBlock:^()
{
//Create user
NSEntityDescription *entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:self.modelManager.mainManagedObjectContext];
User* user = (User *)[[User alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
[user setGuid:@"123123"];
[user setFirstName:@"Markus"];
[user setLastName:@"Millfjord"];
[privateManagedObjectContext insertObject:user];
//Debug before we start to merge...
NSLog(@"Before private save; private context has changes: %d", [privateManagedObjectContext hasChanges]);
NSLog(@"Before private save; main context has changes: %d", [self.modelManager.mainManagedObjectContext hasChanges]);
for (NSManagedObject* object in [privateManagedObjectContext registeredObjects])
NSLog(@"Registered private context object; %@", object);
//Save private context!
NSError* error = nil;
if (![privateManagedObjectContext save:&error])
{
//Oppps
abort();
}
NSLog(@"After private save; private context has changes: %d", [privateManagedObjectContext hasChanges]);
NSLog(@"After private save; main context has changes: %d", [self.modelManager.mainManagedObjectContext hasChanges]);
for (NSManagedObject* object in [privateManagedObjectContext registeredObjects])
NSLog(@"Registered private context object; %@", object);
for (NSManagedObject* object in [self.modelManager.mainManagedObjectContext registeredObjects])
NSLog(@"Registered main context object; %@", object);
//Save main context!
[self.modelManager.mainManagedObjectContext performBlock:^()
{
//Save main context!
NSError* mainError = nil;
if (![self.modelManager.mainManagedObjectContext save:&mainError])
{
//Opps again
NSLog(@"WARN; Failed saving main context changes: %@", mainError.description);
abort();
}
}];
}];
上述方法不起作用,因为它创建了一个临时对象,然后将其插入到上下文中。但是,这个轻微的 mod 可以让事情正常工作,但会阻止我拥有临时对象......;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:self.modelManager.mainManagedObjectContext];
User* user = (User *)[[User alloc] initWithEntity:entity insertIntoManagedObjectContext:privateManagedObjectContext];
因此,我想知道;有什么不同?很明显,肯定有一些区别,但我不明白。
【问题讨论】:
标签: multithreading core-data nsmanagedobject nsmanagedobjectcontext temporary-objects