简体   繁体   English

NSOutlineView仅显示NSTreeController层次结构的前两个级别

[英]NSOutlineView shows only first 2 levels of the NSTreeController hierarchy

I'm populating a NSOUtlineView with a NSTreeController . 我正在用NSTreeController填充NSOUtlineView

The NSTreeController is a 3 levels hierarchy controller (CBMovie, CBDisc and CBEpisode), but only the first 2 levels are displayed in the outline view. NSTreeController是一个3级层次结构控制器(CBMovie,CBDisc和CBEpisode),但是大纲视图中仅显示前2级。

The implementation is the same for all objects: I've implemented methods to specify children, children count and if the object is a leaf. 所有对象的实现都是相同的:我已经实现了用于指定子代,子代计数以及对象是否为叶子的方法。 These methods are correctly called for all objects (also for those ones that are not displayed, the grandchildren: CBEpisode ). 所有对象都正确调用了这些方法(对于那些未显示的对象,孙子对象: CBEpisode )。

In the outline View, everything is displayed correctly for the first 2 level. 在大纲视图中,前两个级别的所有内容均正确显示。 But grandchildren are never displayed, I don't have the option to expand their parent to see them. 但是从不显示孙辈,我没有选择扩大其父母的身份以查看他们。 I can only see CBMovie and CBDiscs. 我只能看到CBMovie和CBDiscs。

I'm wondering if there is another setting I'm missing, about how deep the nodes can expand in NSTreeControllers or NSOutlineView configurations. 我想知道是否还有其他设置,关于节点在NSTreeControllers或NSOutlineView配置中可以扩展的深度。

Below: Implementation in one of the three nodes. 下图:在三个节点之一中的实现。 Each node class has different path to its children. 每个节点类都有其子节点的不同路径。 This is specified in the -(NSArray*)children method (correctly called). 这是在-(NSArray *)children方法(正确调用)中指定的。

-(NSArray*)children
{
    return [[self Episodes] allObjects];
}

-(int)childrenCount
{
    return [[self Episodes] count];
}

-(BOOL)isLeaf
{
    return ![[self Episodes] count];
}

Output of logging code. 日志代码的输出。 The datasource, the NSTreeController, seems to have the correct structure. 数据源NSTreeController似乎具有正确的结构。

   CBMovie
      CBDisc
         CBEpisode
         CBEpisode
    CBMovie
       CBDisc
       CBDisc
       CBDisc
       CBDisc
    CBMovie
       CBDisc
           CBEpisode
           CBEpisode

This is how I populate the NSOutlineView (cell based). 这就是我填充NSOutlineView(基于单元格)的方式。 I don't use datasource methods, but I'm binding it programmatically. 我不使用数据源方法,但以编程方式绑定它。

NSMutableDictionary *bindingOptions = [[NSMutableDictionary alloc] initWithCapacity:2];

        if (metadata.valueTransformer) {
            [bindingOptions setObject:metadata.valueTransformer forKey:NSValueTransformerNameBindingOption];
        }
        [bindingOptions setObject:[NSNumber numberWithBool:NO] forKey:NSCreatesSortDescriptorBindingOption];
        [bindingOptions setObject:[NSNumber numberWithBool:NO] forKey:NSRaisesForNotApplicableKeysBindingOption];

        [newColumn bind:@"value" toObject:currentItemsArrayController withKeyPath:[NSString stringWithFormat:@"arrangedObjects.%@", metadata.columnBindingKeyPath] options:bindingOptions];

Examining the NSTreeController side 检查NSTreeController

The NSTreeController is a 3 levels hierarchy controller, but only the first 2 levels are displayed in the outline view. NSTreeController是一个3级层次结构控制器,但是大纲视图中仅显示前2级。

Have you confirmed that all three levels are loaded into your NSTreeController ? 您是否已确认所有三个级别均已加载到NSTreeController You could do this by logging its contents to the console with the extension below. 您可以通过将其内容记录到具有以下扩展名的控制台中来进行此操作。 If the output produced by this code matches what appears in your outline-view, the problem is probably on the NSTreeController side, not the outline-view. 如果此代码产生的输出与您的大纲视图中出现的输出匹配,则问题可能出在NSTreeController方面,而不是大纲视图。

#import "NSTreeController+Logging.h"

@implementation NSTreeController (Logging)

// Make sure this is declared in the associated header file.
-(void)logWithBlock:(NSString * (^)(NSTreeNode *))block {

    NSArray *topNodes = [self.arrangedObjects childNodes];
    [self logNodes:topNodes withIndent:@"" usingBlock:block];
}

// For internal use only.
-(void)logNodes:(NSArray *)nodes
     withIndent:(NSString *)indent
     usingBlock:(NSString * (^)(NSTreeNode *))block {

    for (NSTreeNode * each in nodes) {
        NSLog(@"%@%@", indent, block(each));
        NSString *newIndent = [NSString stringWithFormat:@"  %@", indent];
        [self logNodes:each.childNodes withIndent:newIndent usingBlock:block];
    }
}

@end

The above code does not need to be adjusted, all you need to do is call it with a customised block: 上面的代码不需要调整,您需要做的就是使用自定义块调用它:

-(void)logIt {

    [self.treeController logWithBlock:^NSString *(NSTreeNode * node) {

        // This will be called for every node in the tree. This implementation
        // will see the object's description logged to the console - you may
        // want to do something more elaborate.
        NSString *description = [[node representedObject] description];
        return description;
    }];

}

Examining the NSOutlineView side 检查NSOutlineView

If all the data seems to have loaded correctly into the NSTreeController you could have a look at how your NSOutlineView is populated. 如果所有数据似乎都已正确加载到NSTreeController ,则可以查看如何填充NSOutlineView The delegate method -[NSOutlineViewDelegate outlineView:viewForTableColumn:item] is a good place to start. 委托方法-[NSOutlineViewDelegate outlineView:viewForTableColumn:item]是一个不错的起点。 The item argument is the NSTreeNode instance, so, before you return the relevant view you can look at this node and make sure it's behaving as expected. item参数是NSTreeNode实例,因此,在返回相关视图之前,您可以查看此节点并确保其行为符合预期。 In your case, you should scrutinize the properties of item objects that are representing CBDisc objects. 在您的情况下,应仔细检查代表CBDisc对象的item对象的属性。 (You may need to click on disclosure buttons to get this method to fire for the relevant objects.) (您可能需要单击显示按钮以使此方法针对相关对象触发。)

-(NSView *)outlineView:(NSOutlineView *)outlineView
    viewForTableColumn:(NSTableColumn *)tableColumn
                  item:(id)item {

    NSTreeNode *node = (NSTreeNode *)item;
    NSManagedObject *representedObject = (NSManagedObject *)node.representedObject;

    // Query the node
    NSLog(@"%@ <%@>", representedObject.description, [representedObject class]);
    NSLog(@"  node is a leafNode: %@", node.isLeaf ? @"YES" : @"NO");
    NSLog(@"  node has child-count of: %lu", (unsigned long)node.childNodes.count);

    // Query the NSManagedObject
    // your stuff here...

    // This is app-specific - you'll probably need to change the identifier.
    return [outlineView makeViewWithIdentifier:@"StandardTableCellView" owner:self];
}

So, I've figured out why. 所以,我知道了原因。

Quite stupid: the main outline column containing the disclosure arrows was 20px width only and the arrows of the children had indentation. 相当愚蠢:包含披露箭头的主轮廓栏宽度仅为20px,孩子的箭头有凹痕。

I'm using the outline column for the arrows only and not the titles of the nodes, that's why it's so narrow. 我只使用大纲列作为箭头,而不是节点的标题,这就是为什么它是如此之窄。

I had disabled indentation and now I can see all arrows. 我禁用了缩进,现在可以看到所有箭头。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM