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個上下文,並且你試圖將保存操作分派到後臺 - 這很容易出錯。如果您有多個上下文,則一次只能在一個線程內使用它們。

相關問題