Основные данные и многопоточность (и привязки, чтобы сделать их более увлекательными) - PullRequest
3 голосов
/ 10 июня 2011

У меня есть этот фоновый поток, который делает несколько вещей с основными объектами данных.Я получаю контекст следующим образом:

- (id)_managedObjectContextForThread;
{    
    NSManagedObjectContext * newContext = [[[NSThread currentThread] threadDictionary] valueForKey:@"managedObjectContext"];
    if(newContext) return newContext;

    newContext = [[NSManagedObjectContext alloc] init];
    [newContext setPersistentStoreCoordinator:[[[NSApplication sharedApplication] delegate] persistentStoreCoordinator]];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(_mergeChangesFromManagedObjectContext:)
                                             name:NSManagedObjectContextDidSaveNotification
                                           object:newContext];

    [[[NSThread currentThread] threadDictionary] setValue:newContext forKey:@"managedObjectContext"];
    return newContext;
}

, затем выбираю некоторые объекты, изменяю их и сохраняю контекст:

- (void) saveContext:(NSManagedObjectContext*)context {
    NSError *error = nil;
    if (![context save:&error]) {
        [[NSApplication sharedApplication] presentError:error];
    }
}

- (void)_mergeChangesFromManagedObjectContext:(NSNotification*)notification;
{
    [[[[NSApplication sharedApplication] delegate] managedObjectContext] performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
                                                                                    withObject:notification
                                                                                 waitUntilDone:YES]; 
}

.. позже я удаляю наблюдателя.Это работает для основной части.Но некоторые свойства не обновляются при слиянии.Свойства, которые были нулевыми до того, как будут обновлены.Те, которые имели значение, остаются прежними.

Я пробовал:

[newContext setMergePolicy:NSOverwriteMergePolicy];

... (и другие политики слияния) в основном контексте, но это не сработало: P

Спасибо за вашу помощь.

Примечание: я привязал значения к NSTableView.Я регистрирую их после слияния.Свойства значений, которые были равны нулю, похоже, работают нормально.

1 Ответ

5 голосов
/ 10 июня 2011

Как вы регистрируете оба контекста для уведомлений? Вам нужно сделать что-то вроде этого:

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

[nc addObserver:self
       selector:@selector(backgroundContextDidSave:)
           name:NSManagedObjectContextDidSaveNotification
         object:backgroundMOC];

[nc addObserver:self
       selector:@selector(mainContextDidSave:)
           name:NSManagedObjectContextDidSaveNotification
         object:mainMOC];

И реализовать обратные вызовы:

// merge changes in background thread if main context changes
- (void)mainContextDidSave:(NSNotification *)notification
{
    SEL selector = @selector(mergeChangesFromContextDidSaveNotification:);
    [backgroundMOC performSelector:selector onThread:background_thread withObject:notification waitUntilDone:NO];
}


// merge changes in main thread if background context changes
- (void)backgroundContextDidSave:(NSNotification *)notification
{
    if ([NSThread isMainThread]) {
       [mainMOC mergeChangesFromContextDidSaveNotification:notification];
    }
    else {
        [self performSelectorOnMainThread:@selector(backgroundContextDidSave:) withObject:notification waitUntilDone:NO];
    }
}
...