根据 NSTextFieldCell 的编辑值更新绑定字典

发布于 2024-07-23 09:46:08 字数 1073 浏览 11 评论 0原文

我正在致力于将一些古老的代码(10.2 时代)从基于 NSCoding/plist 的归档移植到使用 Core Data。 我有一个带有自定义 NSTextFieldCell 的 NSOutlineView。 大纲视图绑定到 NSTreeController 以提供数据。

绑定模型如下所示:

NSTreeController: 托管对象上下文 -> Controller.managedObjectContext

NSOutlineView 的 NSTableColumn 值-> Tree Controller:arrangedObjects:itemDictionary

NSOutlineView 有一个自定义 NSTextFieldCell 子类,它在文本字段旁边添加图像,因此我将 NSManagedObject 的值作为名为 itemDictionary 的 NSMutableDictionary 传递给它,这样我就可以拉取并设置标题和 isChecked 键值。

我遇到问题的地方是更新文本字段的值并将更改后的值传递回我的托管对象实例。 用户双击标题值并对其进行编辑后,它会被传递到 -(id)objectValue,但我不确定下一步是将更新传播到我的 NSManagedObject实例。 到目前为止,我在 NSTextFieldCell 子类中读取和设置值的代码如下:

- (void)setStringValue:(NSString *)aString {
  [super setObjectValue:aString];
}

- (void)setObjectValue:(id <NSCopying>)anObject {  
  id cellValues = anObject;

  [super setObjectValue:[cellValues valueForKey:@"title"]];
  [self setCheckState:[[cellValues valueForKey:@"isChecked"] integerValue]];
}

- (id)objectValue {
  return [super objectValue];
}

I'm working on porting some ancient code (10.2 era) from NSCoding/plist based archiving to using Core Data. I have an NSOutlineView with a custom NSTextFieldCell. The outline view is bound to an NSTreeController to provide the data.

The bindings model looks like this:

NSTreeController:
Managed Object Context -> Controller.managedObjectContext

NSOutlineView's NSTableColumn
Value -> Tree Controller:arrangedObjects:itemDictionary

The NSOutlineView has a custom NSTextFieldCell subclass that adds an image next to the text field, so I am passing the NSManagedObject's values to it as an NSMutableDictionary called itemDictionary so I can pull and set the title and isChecked key values.

Where I am running into issues is updating the text field's value and passing that changed value back to my managed object instance. After the user double-clicks on the title value and edits it, it is passed to -(id)objectValue, but I'm not sure what the next step is to get the update propagated to my NSManagedObject instance. The code I have thus far for reading and setting values in my NSTextFieldCell subclass is below:

- (void)setStringValue:(NSString *)aString {
  [super setObjectValue:aString];
}

- (void)setObjectValue:(id <NSCopying>)anObject {  
  id cellValues = anObject;

  [super setObjectValue:[cellValues valueForKey:@"title"]];
  [self setCheckState:[[cellValues valueForKey:@"isChecked"] integerValue]];
}

- (id)objectValue {
  return [super objectValue];
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

隔岸观火 2024-07-30 09:46:08

我问了一圈,这是有人给我的推荐; 看起来很合理。

在您的 NSCell 子类中,在设置新值时事件循环调用的任何方法中,执行如下操作:

- (void)whateverMethodInCellSubclassIsTriggeredByEventLoop:(id)value {
    NSTableView *tableView = [self controlView];
    NSTableColumn *column = [[tableView tableColumns] objectAtIndex:[tableView editedColumn]];
    NSInteger rowIndex = [tableView editedRow];
    NSDictionary *bindingInfo = [column infoForBinding:NSValueBinding];
    id modelObject = nil;

    if ([controlView isKindOfClass:[NSOutlineView class]]) {
        NSTreeNode *item = [outlineView itemAtRow:rowIndex];
        modelObject = [item representedObject];
    } else if ([controlView isKindOfClass:[NSTableView class]]) {
        NSArrayController *controller = [bindingInfo objectForKey:NSObservedObjectKey];
        modelObject = [[controller arrangedObjects] objectAtIndex:rowIndex];
    }

    [modelObject setValue:value forKeyPath:[bindingInfo objectForKey:NSObservedKeyPathKey]];
}

这是相当通用的代码,它利用表列上可用的绑定信息来获取模型对象和关键路径您的更改应该被推送,并使用通用 KVC 来推送更改。 它应该适用于表格和大纲视图以及任意模型对象,无论是否为核心数据。

I asked around, and this is the recommendation someone gave me; it looks reasonable.

In your NSCell subclass, in whatever method is invoked by the event loop upon setting a new value, do something like this:

- (void)whateverMethodInCellSubclassIsTriggeredByEventLoop:(id)value {
    NSTableView *tableView = [self controlView];
    NSTableColumn *column = [[tableView tableColumns] objectAtIndex:[tableView editedColumn]];
    NSInteger rowIndex = [tableView editedRow];
    NSDictionary *bindingInfo = [column infoForBinding:NSValueBinding];
    id modelObject = nil;

    if ([controlView isKindOfClass:[NSOutlineView class]]) {
        NSTreeNode *item = [outlineView itemAtRow:rowIndex];
        modelObject = [item representedObject];
    } else if ([controlView isKindOfClass:[NSTableView class]]) {
        NSArrayController *controller = [bindingInfo objectForKey:NSObservedObjectKey];
        modelObject = [[controller arrangedObjects] objectAtIndex:rowIndex];
    }

    [modelObject setValue:value forKeyPath:[bindingInfo objectForKey:NSObservedKeyPathKey]];
}

This is fairly generic code that leverages the binding info available on the table column to get the model object and key path to which your changes should be pushed, and to use generic KVC to push the changes. It should work for both table and outline views as well as for arbitrary model objects, Core Data or not.

风渺 2024-07-30 09:46:08

我可能会以不同的方式解决这个问题,通过实现outlineView:willDisplayCell:forTableColumn:item:委托方法,并在那里设置单元格的isChecked属性,而不是从单元格子类中设置。 然后,您只需将该列直接绑定到arrangedObjects.title,因此默认编辑机制将负责在托管对象实例上设置属性。

IIRC,您传递的 item 参数实际上是一个 NSTreeNode 实例,其 returnedObject 属性将为您提供该行的 NSManagedObject 实例,因此您可以通过这种方式从中获取所需的任何信息。

I would probably approach this in a different way, by implementing the outlineView:willDisplayCell:forTableColumn:item: delegate method, and setting the isChecked property of the cell there, rather than from within the cell subclass. You would then just bind that column directly to arrangedObjects.title, so the default editing mechanism would take care of setting the property on the managed object instance.

IIRC, the item parameter you get passed will actually be an NSTreeNode instance whose representedObject property will give you the NSManagedObject instance for that row, so you can get whatever info you need from it that way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文