2

我有一个 NSTableView,其 NSTableColumn 的值绑定到 NSArrayController。arrayController 控制我的核心数据托管对象上下文中的一组实体。

它运行良好,当通过 UI 操作将新实体插入 arrayController 时,tableView 会选择新项目。

但是我会以编程方式在 moc 中创建新实体,然后在 arrayController 中选择新对象。

我尝试了以下方法:

Image *newImage = [Image newImage]; // convenience method to insert new entity into mod.
newImage.title = [[pathToImage lastPathComponent] stringByDeletingPathExtension];
newImage.filename = [pathToImage lastPathComponent];

[self.primaryWindowController showImage:newImage];

showImage: 方法如下:

- (void)showImage:(Image *)image
{
    [self.imagesArrayController fetch:self];
    [self.imagesArrayController setSelectedObjects:@[image]];
}

但是,arrayController 不会更改其选择。

我做错了吗?我假设我在 moc 中创建的 newImage 对象与 arrayController 控制的对象相同。如果这是真的,为什么 arrayController 不改变它的选择?

嗯 - 测试这个假设,我现在已经在运行时检查了 arrayController 的内容。新图像不存在 - 我认为这意味着我已经通过手动插入 moc 来“躲在后面”绑定...

我的 newImage 方便方法是这样的:

+ (Image *)newImage
{
    Image *newImage = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:[[CoreDataController sharedController] managedObjectContext]];
    return newImage;
}

这不符合 KVO 吗?

嗯 - 编辑 2...

我假设它符合 KVO,因为新图像出现在 UI 中。我现在认为将实体插入 moc 和通知 arrayController 之间存在延迟。

我从这个问题中看到新的核心数据对象没有出现在 NSArrayController 安排的对象中(帮助显示在这个问题的右侧),要求 arrayController 获取:应该有助于更新 arrayController,但实际的获取:不会直到下次运行循环运行时才会发生。

我应该使用计时器延迟选择新对象吗?这似乎有点不雅...

4

2 回答 2

2

对 - 解决了这个问题,感谢这个问题:New Core Data object doesn't show in NSArrayController mappedObjects

插入新对象后,我必须直接在 moc 上调用 processPendingChanges:。

所以,我现在的新创建方便方法是:

+ (Image *)newImage
{
    Image *newImage = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:[[CoreDataController sharedController] managedObjectContext]];
    [[[CoreDataController sharedController] managedObjectContext] processPendingChanges];
    return newImage;
}
于 2013-04-11T08:06:58.327 回答
0

如果你想以编程的方式做到这一点,最简单的方法是直接将新的实体对象添加到 NSArrayController 中,就像这样简单:

[self.imagesArrayController addObject:newImage];

这将完成将对象添加到控制器并选择它的技巧。

虽然有一个小故障——我不知道你使用什么视图(NSView、UIView)来呈现 NSArrayController 的内容——但是 NSTableView 不会自动滚动以显示新添加的项目。

我不得不推迟这个(因为添加发生在后来的一些运行循环中),如下所示:

    NSUndoManager *um = self.managedObjectContext.undoManager;
[um beginUndoGrouping];
[um setActionName:NSLocalizedString(@"New Sample", NULL)];
PMWaterSample *sampleToAdd = [self createNewSample];
[self.samplesController addObject:sampleToAdd];

// Actual addition is deferred, hence we delay the scrolling too, on the main-thread's queue.
dispatch_async(dispatch_get_main_queue(), ^{
    [self.samplesController rearrangeObjects];

    // bring last row (newly added) into view
    NSUInteger selectedIdx = [self.samplesController selectionIndex];
    if (selectedIdx != NSNotFound) {
        [self.samplesTable scrollRowToVisible:selectedIdx];
    }
    [um endUndoGrouping];
});

希望这会有所帮助。我从来不用强迫 MOC 处理 PendingChanges。我仍然觉得有更好的方法可以做到这一点,并让数组控制器使其嵌入的 UI 元素滚动并显示新项目,但我不知道如何。

于 2015-11-09T11:47:52.103 回答