ビューベースのNSOutlineViewにコンテンツを提供するNSTreeControllerを備えたドキュメントベースのCore Dataアプリがあります。最終用途が変更できるデータモデルの永続的な「変換可能な」 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 を使用して、変更されたスタイルで行を再描画する必要があるモデル オブジェクトと共に、Outline ビュー デリゲートに通知を送信しています。これは、通知を受け取るデリゲートのコードです。
-(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 を使用してこのスタイル設定を自動的に行うように、色/フォント属性を何らかの方法で行と列にバインドできると便利ですが、それは可能ではないと思います。