【问题标题】:NSOutlineView shows only first 2 levels of the NSTreeController hierarchyNSOutlineView 仅显示 NSTreeController 层次结构的前 2 级
【发布时间】:2015-05-08 11:45:14
【问题描述】:

我正在用NSTreeController 填充NSOUtlineView

NSTreeController 是一个 3 级层次结构控制器(CBMovie、CBDisc 和 CBEpisode),但大纲视图中仅显示前 2 级。

所有对象的实现都是相同的:我已经实现了指定子级、子级计数以及对象是否为叶子的方法。为所有对象正确调用了这些方法(对于那些未显示的对象,孙子:CBEpisode)。

在大纲视图中,前 2 个级别的所有内容都正确显示。但是孙子永远不会显示,我没有选择扩大他们的父母来看到他们。我只能看到 CBMovie 和 CBDiscs。

我想知道我是否缺少另一个设置,即节点可以在 NSTreeControllers 或 NSOutlineView 配置中扩展多深。

下图:三个节点之一中的实现。 每个节点类都有不同的路径到它的子节点。这是在 -(NSArray*)children 方法中指定的(正确调用)。

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

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

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

日志代码的输出。数据源 NSTreeController 似乎具有正确的结构。

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

这就是我填充 NSOutlineView(基于单元格)的方式。我不使用数据源方法,但我以编程方式绑定它。

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];

【问题讨论】:

  • 你能分享一些代码吗?
  • 从你的描述我看不出有什么问题。您能否提供更多细节,例如您的树节点的实现?
  • @renfei 我的树节点都继承自同一个类。您需要更准确地了解什么?
  • @StefanArentz 我在树节点中添加了用于树实现的唯一代码
  • @renfei 好的。确实这就是我发布它的原因,因为我不知道。你需要什么样的额外细节?我需要一些线索

标签: objective-c macos cocoa


【解决方案1】:

检查NSTreeController

NSTreeController 是一个 3 级层次结构控制器,但只有前 2 级显示在大纲视图中。

您是否确认所有三个级别都已加载到您的NSTreeController 中?您可以通过使用下面的扩展名将其内容记录到控制台来做到这一点。如果此代码生成的输出与大纲视图中显示的内容匹配,则问题可能出在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

上面的代码不需要做任何调整,只要用自定义块调用即可:

-(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;
    }];

}

检查NSOutlineView

如果所有数据似乎都已正确加载到NSTreeController,您可以查看您的NSOutlineView 是如何填充的。委托方法-[NSOutlineViewDelegate outlineView:viewForTableColumn:item] 是一个很好的起点。 item 参数是 NSTreeNode 实例,因此,在返回相关视图之前,您可以查看此节点并确保其行为符合预期。在您的情况下,您应该仔细检查代表 CBDisc 对象的 item 对象的属性。 (您可能需要单击公开按钮才能让此方法为相关对象触发。)

-(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];
}

【讨论】:

  • 感谢此代码。是的,NSTreeCOntroller 数据源工作正常。我有所有的孩子,(我已将输出添加到问题中)。但是,问题是什么时候?在 NSOutlineView 中?
  • 在您的问题中,就在日志输出上方,您应该明确说明大纲视图中没有出现的内容,但应该是 - 我假设它是 CBEpisode 的实例。 NSOutlineView 的屏幕截图也会很有帮助。最后包括一些关于您正在实施哪些NSOutlineViewDelegate 方法的信息。
  • 是的,缺少 CBE 剧集。
  • 我正在实现几个委托方法。老实说,我应该仔细阅读它们,因为那部分代码很旧。您是否有任何可能导致问题的委托方法?
  • 感谢您更新您的问题。我已经更新了关于可能提供有用信息的委托方法的答案。
【解决方案2】:

所以,我找到了原因。

非常愚蠢:包含披露箭头的主轮廓列只有 20px 宽度,而孩子的箭头有缩进。

我只使用箭头的大纲列而不是节点的标题,这就是它如此狭窄的原因。

我禁用了缩进,现在我可以看到所有箭头了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-15
    相关资源
    最近更新 更多