子ノードには手を出すな(NSTreeController)

in

このところまたOutlineView+TreeControllerやってます。それでひとつ気づいたことをメモ。

"ツリーコントローラーにストアしているデータをすべてinsertしてもツリー構造にはならない"ということ。読み込んだ子ノードのデータをTreeControllerにinsertすると(親ノードの配下にも表示されますが)親ノードと兄弟のように表示されちゃいますね。ググってみたら、Fetch Predicateに”parent == nil"を指定する(cocoadev:NSTreeController)のが慣例みたいなんですが知りませでした。データの読み込みを確認しながらようやくわかった次第。要するに親ノードが持っている子ノードの展開はTreeControllerが内部で実行することになっているようでプログラムからは親ノードさえadd/insertしてやれば良いようです。当然バインドの場合でも上記の例のようにPredicateを指定する必要があるようです。(Appleの公式ドキュメントとしてどこかに書かれているのかな?)

NSManagedObjectContext *moc = [self managedObjectContext];
NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease];
NSArray* sortDesc = [NSArray arrayWithObject:
  [[[NSSortDescriptor alloc] initWithKey:@"orderNo" ascending:YES] autorelease]];

[fetch setEntity:
  [NSEntityDescription entityForName:@"ChildNodeEntity" inManagedObjectContext:moc]];
[fetch setPredicate:[NSPredicate predicateWithFormat:@"isLeaf == 0"]];
[fetch setSortDescriptors:[self sortDesc]];

NSError *err     = nil;
NSArray *results = [moc executeFetchRequest:fetch error:&err];
if ((err) || (results == nil))
{
  [NSApp presentError:err];
  return;
}

NSUInteger index = 0;

for (ChildNodeEntity *node in results)
{
  [treeController insertObject:node atArrangedObjectIndexPath:
    [NSIndexPath indexPathWithIndex:index]];
  index = index + 1;
}

まあ、実際にやりたかったのはノードの表示順を一定に保つことでCocoaDevのリンクnstreecontroller-and-core-data-sortedにもあったようにノードの中になんらかの方法で順序を示す数値を仕込んでおけばOK。子ノードの展開はTreeControllerお任せになるのでSortDescriptorをバインドする必要もあります。ロード時に特別の処理がなければ僕のコードのようにガリガリコードを書くのは不作法で、やっぱりバインドしたほうがスマートですね。

この記事のトラックバックURL:

http://hippos-lab.com/blog/trackback/371

Comments