3

我有一个线程操作,创建一个新的管理对象,将其保存到持续性存储,然后通过新的VIA NSNotification反对主线程的objectID作进一步处理管理对象上下文不保存到持续性商店

但是,当我尝试从主线程访问新创建的托管对象时,我在后台线程上设置的所有值都返回为空。

**后台线程

// create a new managed object context for this thread 
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init]; 
[context setPersistentStoreCoordinator:[appDelegate persistentStoreCoordinator]]; 
[context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy]; 

// create the object 
MyObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"MyObject" inManagedObjectContext:context]; 
[newManagedObject setAValue:@"A"]; 
[newManagedObject setBValue:@"B"]; 
[newManagedObject setCValue:@"C"]; 

// save it on the main thread 
[context performSelectorOnMainThread:@selector(save:) withObject:nil waitUntilDone:NO]; 

// post notification to main thread, pass the objectID 
NSMutableDictionary *userInfo = [NSDictionary dictionaryWithObject:[newManagedObject objectID] forKey:@"objectID"]; 
[[NSNotificationCenter defaultCenter] postNotificationName:@"doneInsertingObject" object:userInfo]; 
[context release]; 

**主线程

... 
// register notification for background thread 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeContextChanges:) name:NSManagedObjectContextDidSaveNotification object:nil]; 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomethingWithObject:) name:@"doneInsertingObject" object:nil]; 
... 

- (void)doSomethingWithObject:(NSNotification*)noif 
{ 
    if([NSThread isMainThread] == NO) 
    { 
     // run this on the main thread 
     [self performSelectorOnMainThread:_cmd withObject:noif waitUntilDone:NO]; 
     return; 
    } 

    // get managed object from objectID 
    NSDictionary *userInfo = [noif userInfo]; 
    MyObject *object = (MyObject*)[appDelegate.managedObjectContext objectWithID:[userInfo valueForKey:@"objectID"]]; 
    [appDelegate.managedObjectContext refreshObject:object mergeChanges:YES]; 

    // these should return 'A, B, C' but all three return 'nil' 
    NSLog(@"aValue: %@", object.aValue); 
    NSLog(@"bValue: %@", object.bValue); 
    NSLog(@"cValue: %@", object.cValue); 
} 

// merge background thread moc with main moc 
- (void)mergeContextChanges:(NSNotification *)notification 
{ 
    if([NSThread isMainThread] == NO) 
    { 
     // run this on the main thread 
     [self performSelectorOnMainThread:_cmd withObject:notification waitUntilDone:NO]; 
     return; 
    } 

    // fault all updated objects 
    NSSet *updated = [[notification userInfo] objectForKey:NSUpdatedObjectsKey]; 
    for(NSManagedObject *thing in updated) 
    { 
     [[appDelegate.managedObjectContext objectWithID:[thing objectID]] willAccessValueForKey:nil]; 
    } 

    // merge changes to the main managed object context 
    [appDelegate.managedObjectContext mergeChangesFromContextDidSaveNotification:notification]; 

    // force processing of any pending changes 
    [appDelegate.managedObjectContext processPendingChanges]; 
} 

我试图改变合并政策,没有什么区别。

我已经尝试将日志记录添加到上下文合并方法,并且我已经确认在调用主线程上的doSomethingWithObject:方法之后从后台线程接收到“插入”通知

为什么我的数据没有更新到持久存储?

回答

3

我看不到您为后台线程保存上下文的位置。如果是这条线

// save it on the main thread 
[context performSelectorOnMainThread:@selector(save:) withObject:nil waitUntilDone:NO]; 

我不知道它是否正确。您已经从创建它的线程保存上下文,而不是保存在主线程中。

[context save:&error]; 

如需进一步信息,我建议你由Marcus Zarra importing-and-displaying-large-data-sets-in-core-data阅读文章。您可以在最后找到示例代码。此外,您可以在using-core-data-on-multiple-threads中找到更多信息。

希望它有帮助。

+1

其实如果你看看https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdConcurrency.html#//apple_ref/doc/uid/TP40003385它提到“在后台保存线程容易出错“,并且应尽可能在主线程中完成。 – 2012-02-03 18:25:28

+0

你是否尝试过'[self performSelectorOnMainThread:_cmd withObject:noif waitUntilDone:YES];'当你合并上下文? – 2012-02-03 18:32:55

+0

设置waitUntilDone:到“YES”确实解决了我使用的代码的问题。然而,我与那里有更多的具体信息是否是好的/不好的调用保存:从后台线程。如果这很好,我宁愿这样做。 – 2012-02-05 17:29:39

1

您的NSManagedObjectContext必须保存在创建的线程上(如@Flex_Addicted pondered)。

保存在后台线程中后,会发布通知,告诉您将更改从后台上下文合并到主上下文中。

将苹果文档读为“保存在后台线程中容易出错” - 这与使用另一个NSManagedObjectContext无关。他们说,如果你有1个上下文,并且你试图将保存操作分派到后台 - 这很容易出错。如果您有多个上下文,则一次只能在一个线程内使用它们。

相关问题