3 Stimmen

Kerndaten und Multithreading (und Bindungen, damit es mehr Spaß macht)

Ich habe diesen Hintergrund-Thread, der ein paar Dinge mit Kerndatenobjekten tut. Ich erhalte den Kontext wie folgt:

- (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;
}

dann hole ich einige Objekte, ändere sie und speichere den Kontext:

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

später entferne ich den Beobachter. Das funktioniert für den Hauptteil. Aber einige Eigenschaften werden nicht aktualisiert, wenn sie wieder zusammengeführt werden. Die Eigenschaften, die vorher nicht vorhanden waren, werden aktualisiert. Diejenigen, die einen Wert hatten, bleiben gleich.

Ich habe es versucht:

[newContext setMergePolicy:NSOverwriteMergePolicy];

... (und die anderen Zusammenführungsrichtlinien) im Hauptkontext, aber es hat nicht funktioniert :P

Ich danke Ihnen für Ihre Hilfe.

Hinweis: Ich habe die Werte an eine NSTableView gebunden. Ich protokolliere sie nach der Zusammenführung. Die Werteigenschaften, die null waren, scheinen gut zu funktionieren.

5voto

David Punkte 7252

Wie registrieren Sie die beiden Kontexte für Benachrichtigungen? Sie müssen etwa so vorgehen:

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

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

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

Und implementieren Sie die Rückrufe:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X