Poprawny sposób aktualizacji NSTableView w aplikacji Core Data

Mam projekt Core Data z NSTableView, gdzie kolumny są powiązane z kontrolerem NSArrayController. Z kolei zawartość kontrolera jest powiązana z głównym kontekstem obiektu zarządzanego aplikacji AppDelegate.

Podklasowałem NSTextFieldCell, aby zapewnić bardziej niestandardowy sposób wyświetlania danych. Wszystko wydaje się działać dobrze, ale kiedy wyliczam obiekty w kontekście i zmieniam atrybut, NSArrayController nie wydaje się przekazywać nowych wartości do tabeli. Wiem, że są one zmieniane, gdy działają sortDescriptors, a tabela organizuje się zgodnie z nowymi danymi, ale nadal wyświetla stare wartości. Zgaduję, że jest to wynikiem recyklingu NSCell, które wyświetlają dane: chociaż podstawowe wartości zostały zmienione w DB danych podstawowych, których nie rysują ponownie.

Po wypróbowaniu różnych powiadomień KVO[myArrayController willChangeValueFor: aKeyPath] i odpowiadającedidChange jak również po prostu[myTable reloadData]. Moim jedynym rozwiązaniem było odczepienie powiązania managedObjectContext kontrolera i ponowne zawieszenie go po przetworzeniu, tak jak poniżej:

self.hasBackgroundOp = YES;
self.isCancelled = NO; //can get changed with a 'cancel' button in the UI
    if (self.managedObjectContext.hasChanges) {
        [self. managedObjectContext save:nil];
    }
    [myArrayController setManagedObjectContext:nil]; //brutal un-hooking of controller
    dispatch_group_t dispatchGroup = dispatch_group_create();
    dispatch_group_async(dispatchGroup, dispatch_get_global_queue(0, 0), ^{
        .
        .
        // create a thread context, set the persistent store co-ord
        // and do some processing on the
        // NSManagedObjects that are fetched into an array just
        // for the purpose of this thread
        .
        .
        [ctx save:&error];
        //and after the processing is finished then refresh the table
        dispatch_async(dispatch_get_main_queue(), ^{
            [myArrayController setManagedObjectContext:self.managedObjectContext]; //this forces re-drawing of the table
            self.hasBackgroundOp = NO;
            self.isCancelled = NO;
        });
    });

Wydaje się to naprawdę brutalne[myArrayController setManagedObjectContext:nil]; a następnie ponowne ustawienie, aby odświeżyć zawartość tabeli. Po prostu nie mogę uwierzyć, że zrobiłem to poprawnie, chociaż działa dobrze. Czy ktoś mógłby doradzić lepszy sposób? Dzięki!

UPDATE: ustawienie kontekstu obiektu zarządzanego nie rozwiązuje problemu. Wydaje się, że przestał działać. Jeśli kod jest uruchamiany dwa razy z rzędu, aplikacja po prostu się zawiesza. Skomentuj-setManagedObjectContext: linie i kod można uruchamiać tyle razy, ile potrzeba.

W odpowiedzi na komentarze moja niestandardowa komórka używa następujących elementów, aby się wyświetlić:

NSInteger index = [[self stringValue] integerValue] + 1;
NSAttributedString *cellText = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%lu",index] attributes:attributes];
NSRect textRect;
textRect.origin = cellFrame.origin;
textRect.origin.x += (cellFrame.size.width - cellText.size.width) / 2;
textRect.origin.y += (cellFrame.size.height - cellText.size.height) / 2;
textRect.size.width = cellText.size.width;
textRect.size.height = cellText.size.height;
[cellText drawInRect:textRect];

Kontroler tablicy jest skonfigurowany w głównej nib i ma kontekst obiektu zarządzanego związany z aplikacją AppDelegate. W nib nie ma żądań pobierania ani predykatów - deskryptor sortowania jest związany w kodzie AppDelegate:

[myArrayController setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:kINDEX ascending:YES]]];

questionAnswers(1)

yourAnswerToTheQuestion