Cocoa如何对基于NSTableView的视图中的特定行强制执行特定的编辑行为?

时间:2015-04-28 19:17:03

标签: objective-c cocoa nstableview

我有一个简单的基于NSTableView的视图,其中一列填充了Core Data实体,而row的视图只包含一个NSTextField。我只需要第一行不可编辑,并以红色显示。我试着在applicationDidFinishLaunching:

中的某个地方
NSView *myView = [myPlaylistsTableView viewAtColumn:0 row:0 makeIfNecessary:NO];

NSArray *mySubviews = [myView subviews];

NSTextField *myTextField = [mySubviews firstObject];

[myTextField setEditable:NO];
NSDictionary *myDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSColor redColor],NSForegroundColorAttributeName, nil];
NSAttributedString *myRedAttributedString = [[NSAttributedString alloc] initWithString:@"All Songs" attributes:myDictionary];

[myTextField setAttributedStringValue:myRedAttributedString];

但是只要在表格中添加新元素或执行拖动,第一行就会再次编辑。我试图编写一个值转换器,将NSTextField可编辑绑定绑定到数组控制器selectionIndex,如果selectionIndex为0,则返回NO,在所有其他情况下返回yes。这不起作用,值绑定的各种配置有条件地设置可编辑复选框。我想NSTableView的一个子类也可以做到这一点,但我在这方面有点迷失。 任何帮助总是非常感激。感谢。

正如@Joshua Nozzi所建议的那样,我正在为表视图实现这个委托方法:

-(NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{

NSView *myView = [tableView makeViewWithIdentifier:[tableColumn identifier] owner:self];

if (tableView == myPlaylistsTableView)
{
if (row == 0)
{
    NSArray *mySubviews = [myView subviews];

    NSTextField *myTextField = [mySubviews firstObject];

    [myTextField setEditable:NO];
    NSDictionary *myDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSColor redColor],NSForegroundColorAttributeName, nil];
    NSAttributedString *myBoldAllSongsString = [[NSAttributedString alloc] initWithString:@"All Songs" attributes:myDictionary];

    [myTextField setAttributedStringValue:myBoldAllSongsString];

}
}
return myView;
}

但我必须遗漏一些东西,因为该方法被调用正确的NSTableView和row = 0,代码被执行但我仍然没有红色字符串,文本字段是可编辑的。

再次感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您正在尝试定位单元格视图并永久地设置它。" NSTableView并非如此。每次重新加载一行或整个表时,受影响行的视图都会刷新""刷新"。

自定义它们的适当位置在NSTableViewDelegate协议方法-tableView:viewForTableColumn:row:中(请记住将实现此方法的控制器设置为表视图的委托)。

根据OP的更新进行更新

有些观点:

  1. 使用表格列的标识符作为您的单元格视图的标识符有点奇怪,因为两者可能不同。特别是如果您在同一列中有多个可能的单元格类型(常见情况)。最好进入为每个单元格视图使用唯一标识符的做法,并且如果您有多个列,则仅使用列标识符来标识列。

  2. 您在 之外查看 if()条件,检查哪个表格正在询问。如果你只有一张桌子,请不要费心检查;如果您可能有多个使用该控制器,请确保与每个表相关的所有内容(包括-makeViewWithIdentifier :)都在其相关条件内。返回myView也是如此 - 如果没有表匹配,那么你的最后一次返回应为零,以便进行最佳练习。

  3. 您似乎只在row == 0时才配置您的单元格视图,但是您没有考虑已经配置为第0行但正在重复使用行的重用视图&gt ; 0。你可能会看到"有趣的"所有行的行为> 0在需要大量滚动的大表中。

  4. 您确定单元格视图的第一个子视图是NSTextField吗?您是否在调试器控制台中看到任何消息(例如" ...does not respond to selector...")?或者,如果您在[myTextField setEditable:NO]行设置断点,那么当调试器暂停时,myTextField是否为零?这里的最佳做法是将您自己的视图子类IBOutlet s创建到您要与之交互的任何子视图中,然后以这种方式更新它们。在编辑单元格视图时,依赖于其子视图列表是一个混淆和未来错误的处方,即使它最初正在工作。

  5. 与4相关,如果你需要的只是一个文本字段作为你的单元格,为什么不使用库存NSTableCellView类(它有自己的-textField插座)所以你可以告诉它{{1} }

  6. myView.textField.attributedStringValue = someAttributedString有单独的方法来设置其字符串值的字体和颜色。为什么不利用这些而不是创建和设置属性字符串?

  7. 添加:忘了提到绑定。即使您正确获取对文本字段的引用,在此处设置其属性也不会对您有所帮助,因为绑定可能会覆盖它们。更容易放弃绑定并在NSTextField旁边实施NSTableDataSource协议,并在数据更改时自行处理表格视图。关于UI更新的时间安排,你会给自己带来很多麻烦和困惑。

  8. 基于以上内容的重写示例:

    NSTableViewDelegate