我有一个基于文档的核心数据应用程序,其 NSTreeController 将内容提供给基于视图的 NSOutlineView。我正在“样式化”(设置文本颜色、背景颜色等)基于我的数据模型中的持久“可转换”NSColor 和 NSFont 属性的行,最终用户可以修改这些属性。当弹出新行时,它会使用数据模型中设置的颜色/字体显示内容。这是设置行背景颜色的委托/数据源代码:
- (void) outlineView:(NSOutlineView *)outlineView
didAddRowView:(NSTableRowView *)rowView
forRow:(NSInteger)row
{
// Get the relevant nodeType which contains the attributes
QVItem *aNode = [[outlineView itemAtRow:row] representedObject];
if (aNode.backColor)
{
rowView.backgroundColor = aNode.backColor;
}
}
但是,当样式属性更改时,我希望使用新样式值重绘关联的可见行。每次更改“样式”属性时,我都使用 NSNotificationCenter 向大纲视图委托发送通知,其中模型对象的行需要使用更改后的样式重新绘制。这是接收通知的委托中的代码。
-(void) styleHasChanged: (NSNotification *)aNotification
{
NSTreeNode *aTreeNode = [myTreeController treeNodeForModelObject:aNotification.object];
[myOutlineView reloadItem:aTreeNode];
}
我在这里的假设是我可以导航树控制器以找到代表我的模型对象的树节点,然后要求大纲视图重绘该树节点的行。这是树控制器中的“添加”代码,它遍历树以查找对象 - 效率不高,但我认为没有其他方法。
@implementation NSTreeController (QVAdditions)
- (NSTreeNode *)treeNodeForModelObject:(id)aModelObject
{
return [self treeNodeForModelObject:aModelObject inNodes:[[self arrangedObjects] childNodes]];
}
- (NSTreeNode *)treeNodeForModelObject:(id)aModelObject inNodes:(NSArray*)nodes
{
for(NSTreeNode* node in nodes)
{
if([node representedObject] == aModelObject)
return node;
if([[node childNodes] count])
{
NSTreeNode * treeNode = [self treeNodeForModelObject:aModelObject inNodes:[node childNodes]];
return treeNode;
}
}
return nil;
}
所以有时这有效并且行重绘,有时则无效。委托方法“styleHasChanged:”总是被调用,树控制器总是返回一个对应的树节点(实际上是NSTreeNode的一个子类)。但通常大纲视图无法识别树节点,并且不会重绘行。就像树控制器返回了与过去提供大纲视图的树节点对象不同的树节点对象。但奇怪的是,有时它确实有效,并且用新的背景颜色重新绘制了右行。如果我将该行折叠到视图之外并再次将其弹出,则它会正确重绘。
任何人都知道为什么它有时会起作用而不是其他时候吗?
能够以某种方式将颜色/字体属性绑定到行和列会很好,以便大纲视图使用 KVO 自动进行此样式设置,但我认为这是不可能的 - 是吗?