NSOutlineView/NSTreeControllerのサンプル読み...難航中

この二日ばかり、時間を見つけてOutlineViewを使うサンプルSourceViewを読んでいます。最終的にはCoreDataでOutlineViewを使ってアプリを作成予定なんですがNSTreeControllerを使ったサンプルは意外と少なくて....ツリーに表示するノードクラス(BaseNodeクラス)の解析からはじめてますが難航中。

ノードに関するメソッドとして、子ノードへのアクセッサ・リーフノード判定などは見たとおりなんですが、子(孫・曾孫...)ノード取得やリーフノードの取得など(性質上当然とはいえ)再帰メソッドとして実装されているのでソースを追うのはちょっと大変。複雑なのは、レシーバーがあるノード群の子孫ノードであるかを判定するメソッド-(BOO) isDescendantOfNodes:(NSArray*)nodesなどはちょっと複雑。二つのメソッドから構成されていて、一方は再帰となっているので目を眩まされちゃいます。

NSEnumerator *enumerator = [nodes objectEnumerator];
id node = nil;
while (node = [enumerator nextObject])
{
  // check all the sub-nodes
  if (![node isLeaf])
  {
    if ([self isDescendantOfOrOneOfNodes:[node children]])
    {
      return YES;
    }
  }
}

というのがメソッドisDescendantOfNodes:(NSArray*)nodesの本体。ここから呼び出しているisDescendantOfOrOneOfNodesが、

NSEnumerator *enumerator = [nodes objectEnumerator];
id node = nil;
while (node = [enumerator nextObject])
{
  if (node == self)
  {
    return YES;   // we found ourselv
   }
  // check all the sub-nodes
  if (![node isLeaf])
  {
    if ([self isDescendantOfOrOneOfNodes:[node children]])
    {
      return YES;
    }
  }
}
return NO;

一見、似たようなメソッドですがこちらがノード配列から自分自身を探すメソッドの本体です。このメソッドは再帰していて子ノード・孫ノード・曾孫ノード...と自分自身が見つかるまで掘り下げて検索していきます。これらのメソッドはサンプルでは使用されていませんがどんな場面で使うのかは???です。また、BaseNodeクラスでは親ノードへの参照を保持せず、parentFromArray:(NSArray*)nodesというメソッドを実装しています。自分自身を子ノードとして包含するノードを検索していくメソッド(もちろん再帰メソッド)ですがこれだとルートノードから検索するしかないような気がするので不経済な気がします。なにより複雑になるし。単にこういうやり方もあるよというサンプルなのかもしれませんがこのあたりもじっくり考えてみないと。

コードを読めば読むほど疑問が沸き起こるのですが、読み込んでいくことで解決していくことを期待しつつ、わかった(つもり)のところからまとめていきます。

-(NSMutableArray*)children
子ノードの配列を返す
-(void)setChildren:(NSArray*)newChildren
子ノードを追加する
-(BOOL)isLeaf
リーフノードか否かを調る
-(void)setLeaf:(BOOL)flag
ノードがリーフノードか否かのフラグをセットする。YESをセットする場合、子ノードを保持する配列に自分自身をセット。子ノードでない場合、子ノードを保持する配列を初期化(空の配列を作成)
-(NSArray*)descendants
子孫(子・孫・曾孫...)ノードを配列として返します。再帰アルゴリズムを使用して実装しています。
-(NSArray*)allChildLeafs
全リーフノード(子・孫・曾孫...含む)を配列として返す
-(NSArray*)groupChildren
子ノード中、リーフノードでないノードを配列として返す。(孫・曾孫...ノードは含まず)
-(BOOL)isDescendantOfOrOneOfNodes:(NSArray*)nodes
引数で指定されたノードグループに含まれているか、またはノードグループのサブノード(子ノード)に含まれているか調べる。(isDescendantOfNodes:(NSArray*)からアクセス)
-(BOOL)isDescendantOfNodes:(NSArray*)nodes
引数で示されたノードグループの子孫であるか調べる
-(id)parentFromArray:(NSArray*)array
親ノードを指定されたノード配列から検索
-(void)removeObjectFromChildren:(id)obj
子ノードから指定されたノードを削除

サンプルでは、独自にこのNodeBaseクラスを定義していますが、v10.5からはNSTreeNodeというクラスがあってこちらを使うのが新しいり流儀とい気もするのですがまだ不透明で何も見えていません。しばらく、このサンプルと格闘が続きそうな予感。

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

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

Comments


Apple Store(Japan)