macos - 实现 NSBrowserDelegate 协议(protocol)的问题

标签 macos cocoa nsbrowser

我能够让我的 NSBrowser 实例在第一列中显示正确的数据。然而,当我选择其中一个选项时,下一列仅显示同一组选项。我已经阅读了文档,查看了 Apple 的所有相关示例代码,以及我在互联网上可以找到的几乎所有内容,但我根本无法找出实现所需方法的正确方法。我向浏览器提供的数据是一组字典。每个字典依次包含一个“子”键,它是另一个字典数组。这些字典有自己的“子”键,它们也是字典数组等。使用 JSON 进行描述(对象是字典,数组是数组),它看起来像这样:

data = [
    {
        name: 'David',
        children:[
            {
                name: 'Sarah',
                children: {...}
            },
            {
                name: 'Kevin',
                children: {...}
            }
        ]
    },
    {
        name: 'Mary',
        children:[
            {
                name: 'Greg',
                children: {...}
            },
            {
                name: 'Jane',
                children: {...}
            }
        ]
    }
]

因此第一列应显示“David”和“Mary”。如果选择“David”,下一列应显示“Sarah”和“Kevin”,依此类推。

我当前的实现依赖于我创建的自定义方法,该方法应该将浏览器的索引路径从提供的数据转换为相应的 NSArray 级别。这个方法看起来像:

- (NSArray *)getSelectionInBrowser:(NSBrowser *)browser
{
    NSArray *selection = browserData;
    NSIndexPath *path = [browser selectionIndexPath];
    for (NSUInteger i = 0; i < path.length; i++) {
        selection = [[selection objectAtIndex:i] objectForKey:@"children"];
    }
    return selection;
}

我对所需 NSBrowserDelegate 协议(protocol)方法的实现如下所示:

- (NSInteger)browser:(NSBrowser *)sender numberOfRowsInColumn:(NSInteger)column
{
    return [[self getSelectionInBrowser:sender] count];
}

- (NSInteger)browser:(NSBrowser *)browser numberOfChildrenOfItem:(id)item {
    return [[self getSelectionInBrowser:browser] count];
}

- (id)browser:(NSBrowser *)browser child:(NSInteger)index ofItem:(id)item {
    return [self getSelectionInBrowser:browser];
}

- (BOOL)browser:(NSBrowser *)browser isLeafItem:(id)item {
    return ![item isKindOfClass:[NSMutableArray class]];
}

- (id)browser:(NSBrowser *)browser objectValueForItem:(id)item {
    return nil;
}

- (void)browser:(NSBrowser *)browser willDisplayCell:(NSBrowserCell *)cell atRow:(NSInteger)row column:(NSInteger)column {
    NSArray *selection = [self getSelectionInBrowser:browser];
    cell.title = [[selection objectAtIndex:row] objectForKey:@"name"];
}

NSBrowser 的第一列填充了正确的名称。但是,一旦我做出选择,程序就会崩溃,并出现错误 -[__NSArrayM objectAtIndex:]: index 4超出范围[0 .. 0]。进行一些调试后,崩溃的代码行是我的自定义 getSelectionInBrowser: 中的 objectAtIndex: 调用。

这并不完全让我感到惊讶,因为即使在崩溃之前,我也认为我依靠自定义方法来检索当前选择是做错了什么。我想这项工作应该在委托(delegate)方法本身内完成,并且当正确实现时,当前选择应该可以在许多这些方法中提供的 item 变量中访问。但是,我无法让它发挥作用。 item 变量似乎始终只是根数据对象,而不是反射(reflect)最“深入”的选择。

那么我该如何纠正我的实现呢?

最佳答案

解决了!这是我的最终工作代码。不需要自定义 getSelection... 方法,而且我拥有的几个委托(delegate)方法也是不必要的(只有您不使用“基于项目的 API”)。

- (NSInteger)browser:(NSBrowser *)browser numberOfChildrenOfItem:(id)item {
    if (item) {
        return [[item objectForKey:@"children"] count];
    }
    return [browserData count];
}

- (id)browser:(NSBrowser *)browser child:(NSInteger)index ofItem:(id)item {
    if (item) {
        return [[item objectForKey:@"children"] objectAtIndex:index];
    }
    return [browserData objectAtIndex:index];
}

- (BOOL)browser:(NSBrowser *)browser isLeafItem:(id)item {
    return [item objectForKey:@"children"] == nil;
}

- (id)browser:(NSBrowser *)browser objectValueForItem:(id)item {
    return [item objectForKey:@"name"];
}

第一种方法是告诉 NSBrowser 应该有的行数。第二种方法是确定给定行(索引)中应表示哪些数据。在这两种情况下,您必须首先检查 item 是否确实存在。如果没有,那是因为您位于数据的根(NSBrowser 中的第一列)。只有当 NSBrowser 中的一行(或项目!)被选中时,item 变量才会保存任何内容。 final方法应返回您希望在给定行中显示的字符串。

希望这对将来的人们有所帮助。

关于macos - 实现 NSBrowserDelegate 协议(protocol)的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15811712/

相关文章:

linux - 我可以使用 ssh 登录另一个主机并自动将 "su"发送给另一个用户吗?

ruby - 将 mechanize 与 watir + phantomjs 一起使用

cocoa - NSBrowser 图像未显示在单元格中

objective-c - OS X 10.8+ 中带有 Finder 等部分的 NSBrowser

objective-c - 苹果操作系统 X : How to force a Field Editor to scroll instead of wrap text?

c++ - 我在 Mac 上的什么地方放置 MySQL C++ 连接器文件?

objective-c - NSNotification/绑定(bind)?

ios - 将两个可变宽度 View 保持在 super View 中心的约束

cocoa - 应该由 View 还是 Controller 负责拖动处理?

cocoa - 如何单击segmentedControl对象并使用它来更改 View ?