2013-04-04 134 views
2

我能够让我的NSBrowser实例在第一列中显示正确的数据。然而,当我选择其中一个选项时,下一列只显示相同的一组选项。我已经阅读了文档,查看了所有Apple的相关示例代码,以及我在互联网上可以找到的所有内容,但是我根本找不到实现所需方法的正确方法。我提供给浏览器的数据是一组字典。每个字典又包含一个“儿童”键,这是另一个字典的数组。而这些词典有同样词典等使用JSON用于说明目的的阵列自己的“孩子”键(对象是字典,数组是数组),它看起来像这样:实现NSBrowserDelegate协议的问题

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

所以第一列应该显示“大卫”和“玛丽”。如果选择“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协议方法实现的样子:

- (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 beyond bounds [0 .. 0]。在进行一些调试之后,它崩溃的代码行是我自定义的getSelectionInBrowser:中的objectAtIndex:调用。

这并不完全让我感到惊讶,因为即使在崩溃之前,我仍然认为我依靠这种自定义方法来检索当前选择,从而做错了什么。我想这个工作应该在委托方法本身内完成,并且如果正确实施,当前的选择应该可以在item变量中访问,该变量在许多这些方法中提供。但是,我无法让它工作。 item变量似乎总是只是根数据对象,而不是反映最“深入”的选择。

那么如何纠正我的实施?

回答

4

解决了!这是我最后的工作代码。没有必要使用这种自定义的方法,而且我有一些委托方法是不必要的(只使用你不会使用“基于项目的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变量才能保存任何内容。最后的方法应该返回你想要在给定行中显示的字符串。

希望这可以帮助未来的人。

+0

未来的人都感谢你的帮助。 – 2016-07-27 21:00:12