Контекст управляемого объекта не сохраняется в постоянном хранилище - PullRequest
3 голосов
/ 03 февраля 2012

У меня есть многопоточная операция, которая создает новый управляемый объект, сохраняет его в постоянном хранилище, а затем передает идентификатор объекта нового возражения через NSNotification в основной поток для дальнейшей обработки

Однако, когда я пытаюсьдля доступа к вновь созданному управляемому объекту из основного потока все значения, которые я установил в фоновом потоке, возвращаются как пустые.

** фоновый поток

// 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];
}

Я попытался изменить политику слияния, и не было никакой разницы.

Я попытался добавить запись в метод слияния контекста, и я подтвердил получение "вставленного" уведомления из фона.thread before вызывается метод doSomethingWithObject: в основном потоке.

Почему мои данные не обновляются в постоянном хранилище?

Ответы [ 2 ]

3 голосов
/ 03 февраля 2012

Я не вижу, где вы сохраняете контекст для фонового потока.Если это эта строка

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

Я не знаю, правильно ли это.Вы сохранили контекст из потока, который его создал, а не из основного потока.

[context save:&error];

Для получения дополнительной информации я предлагаю вам прочитать статьи Маркуса Зарры импорт-отображение-Большие-наборы данных-в-колонковых данных .Вы можете найти образец кода в конце.Кроме того, вы можете найти дополнительную информацию в используя-core-data-on-множественные потоки .

Надеюсь, это поможет.

1 голос
/ 04 февраля 2012

Ваш NSManagedObjectContext должен быть сохранен в потоке, в котором он был создан (как обдумано @Flex_Addicted).

После сохранения в фоновом потоке будет опубликовано уведомление с предложением объединить изменения из фонового контекста в основной.

В документах Apple указано «Сохранение в фоновом потоке подвержено ошибкам» - это не связано с использованием другого NSManagedObjectContext. Они говорят, что если у вас есть 1 контекст, и вы пытаетесь отправить операцию сохранения в фоновый режим - это подвержено ошибкам. Если у вас несколько контекстов, они должны использоваться одновременно только в одном потоке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...