在Core Data应用程序中更新NSTableView的正确方法

时间:2012-12-23 10:20:24

标签: cocoa core-data nsarraycontroller

我有一个带有NSTableView的Core Data项目,其中列绑定到NSArrayController。反过来,控制器的内容绑定到AppDelegate的主要托管对象上下文。

我已经对NSTextFieldCell进行了细分,以提供更加个性化的数据显示方式。一切似乎都运行良好但是当我通过上下文中的对象枚举并更改属性时,NSArrayController似乎似乎没有将新值传递给表。我知道他们正在被改变,因为sortDescriptors工作,并且表根据新数据组织自己,但仍然显示旧值。我猜这归结于显示数据的NSCell的回收:尽管核心数据DB中的基础值已经改变,但它们并没有重新绘制。

使用[myArrayController willChangeValueFor: aKeyPath]和相应的didChange以及[myTable reloadData]尝试各种KVO通知后。我唯一的解决方案是取消挂钩控制器的managedObjectContext绑定,并在处理后重新挂钩,如下所示:

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

执行[myArrayController setManagedObjectContext:nil];然后再次设置它只是为了刷新表的内容似乎非常残酷。我无法相信我已经正确地完成了这项工作,尽管它运作得很好。任何人都可以提出更好的建议吗?谢谢!

更新:实际设置托管对象上下文并不能解决问题。它似乎停止了工作。如果代码连续运行两次,那么应用程序就会挂起。注释掉-setManagedObjectContext:行,代码可以根据需要运行多次。

在回复评论时,我的自定义单元格使用以下内容显示自己:

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

阵列控制器在主nib中设置,并将其托管对象上下文绑定到AppDelegate。 nib中没有获取请求或谓词 - 在AppDelegate的代码中绑定了一个排序描述符:

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

Grab of controller options

1 个答案:

答案 0 :(得分:1)

认为我已找到它 - 我在线程处理结束时添加了以下内容并在主线程上执行它:

[self.managedObjectContext reset];
[myArrayController fetch:self];

重置MOC显然会将其清除,从而迫使控制器重绘单元格。 -fetch似乎是必要的,否则表格会变成空白......