如何有效地压平NSOutlineView?

时间:2012-08-05 18:20:06

标签: objective-c macos cocoa nsoutlineview nstreecontroller

我有一个绑定到我的NSTreeController的NSOutlineView。使用以下命令使用数据设置NSTreecontroller(myTreeController)的内容:     [self.myTreeController setContent:self.myArrayOfFiles]; 该数组的内容由NSTreeNode父对象和使用NSTreeNode子类(TKnode)添加的子对象组成:

[TKnode treeNodeWithRepresentedObject:myRootObject]

这非常有效,可以正确显示我的NSoutlineView。但是当我想迭代NSOutlineView的内容时,我需要将其展平并将对象存储在数组中。这是我需要一些帮助的地方,因为我所拥有的解决方案不是最优的,并且可能容易出错。

我首先使用以下命令返回NSTreeController的内容:

 - (NSArray *)rootNodes;
{
    return [[myTreeController arrangedObjects] childNodes] ;
}

这将返回一个大小为1的NSTreeControllerTreeNode数组,该数组包含树结构。然后,我使用childNodes方法访问树结构的第一层。

- (NSArray *)flattenedNodes
{
    NSMutableArray *mutableArray = [NSMutableArray array]; 
    for (TKnode *rootnode in [self rootNodes]){
        for (TKnode *node in [rootnode childNodes]){

            if (![[node representedObject] isLeaf]){
                [mutableArray addObjectsFromArray:[self descendants:[node representedObject]]];
            }
            else {
                [mutableArray addObject:[[node representedObject] representedObject]];
            }
        }
    }
    DLog(@"My files: %lu",[mutableArray count]);
    return [[mutableArray copy] autorelease];
}

使用以下方法递归访问子项的子项:

- (NSArray *)descendants:(TKnode *) node
{
    NSMutableArray *descendantsArray = [NSMutableArray array]; 
    for (TKnode *mynode in [node childNodes]) {

        [descendantsArray addObject:[mynode representedObject]];

        if (!mynode.isLeaf){
            [descendantsArray addObjectsFromArray:[self descendants:mynode]];
        }
    }
    return [[descendantsArray copy] autorelease]; // return immutable
}

这可以工作并返回一个包含我所有对象的数组,而不是NSTreeNodes,但是我感兴趣的对象。但是我似乎很容易在一个对象上有时两次调用representObject来访问我的对象。这是我应该使用NSTReeController和NSTreeNodes的方式吗?有没有更好的办法?我首先想要使用NSTreeNode和NSTreeController的原因是为了获得一些已经实现的免费方法,例如sort和arrangeObjects,我习惯使用NSTableView。但是我用来访问NSTreeController内容的方法似乎不正确?我应该使用arrangedObjects来获取NSTReeController的内容还是应该使用不同的方法?任何有关如何正确展平NSOutlineView的建议都非常受欢迎。

谢谢!干杯,特隆德

2 个答案:

答案 0 :(得分:1)

这个问题原来是一个真正的风滚草(我一个月内的第二个),所以我想跟进一些更多的信息。我最终使用上面发布的代码来展平我的NSOutlineView,因为我无法找到更好的选择。当你必须递归迭代未知数量的子文件夹(在我的情况下)时,这似乎是每次达到更深层次时调用descendants方法的最佳选项。我发现了一个非常有用的网站,其中包含许多有用的NSTreeController扩展here,它使用的方法与我采用的方法相同。除非有人帮我找出一个更快更好的算法来展平NSTreeController的arrangeObjects,我相信我会坚持这种方法。

干杯,特隆德

更新:在解决方案问题之后,我决定发布我的方法来展平大纲视图。我希望他能帮助别人。

- (void) flattenOutlineview
{
    NSMutableArray *nodeArray = [NSMutableArray array];
    [self.myFlattenedFiles removeAllObjects];
    [self.myFlattenedNodes removeAllObjects];
    [self.myIndexDict removeAllObjects];
    [nodeArray removeAllObjects];

    for (SDNode *rootnode in self.rootNodes)
    {
        [nodeArray addObject:rootnode];

        [self.myIndexDict setObject:[rootnode indexPath]
                             forKey:[[[rootnode representedObject] representedObject] fullpathL]];

        for (SDNode *node in [rootnode childNodes])
        {
            if (node.isLeaf){
                [nodeArray addObject:node];
                 [self.myIndexDict setObject:[node indexPath]
                                 forKey:[[[node representedObject] representedObject] fullPathCopy]];
            }
            else {
                [nodeArray addObjectsFromArray:[self descendants:node]];
                [self descendantsIndex:node];
           }  
       }  
   }
   [self.myFlattenedNodes setArray:[nodeArray copy]];

   for (SDNode *node in self.myFlattenedNodes)
   {
       [self.myFlattenedFiles addObject:[[node representedObject] representedObject]];
   }
}

答案 1 :(得分:0)

从我刚写的另一个答案中看出这个链接。如果扩展/显示树中的所有内容,则可以使用:

for (NSUInteger row = 0; row < [outlineView numberOfRows]; row++)
{
    NSTreeNode* node = [outlineView itemAtRow:row];
    [nodeArray addObject:node];
}

outlineView的行基本上是一个扁平的树。而且你可以扩展每个项目,同时迭代以获得所有项目。