基于视图的 NSOutlineView 中的空单元格

问题描述 投票:0回答:2

更新:链接到完整源代码(下载

我正在尝试实现基于视图的 NSOutlineView (Sourcelist),但我遇到了问题。为了说明这一点,我创建了一个简约的示例。

我有一个简单的类,名为 Person。每个人都有一个名字(NSString),也许还有一些孩子(NSArray)。我添加了一个 NSOutlineView,将其连接到 IBOutlet,将自己设置为数据源,并实现了 NSOutlineViewDataSource 方法。

首先考虑基于 CELL 的 NSOutlineView 的情况:

- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
    // We are at the root
    if (!item)
    {
        return [self.persons count];

    }

    // We are at an internal node
    Person *person = (Person *)item;
    return [person.children count];
}

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
    // We are at the root
    if (!item)
    {
        return self.persons[index];
    }

    // We are at an internal node
    Person *person = (Person *)item;
    return person.children[index];
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
    Person *person = (Person *)item;
    if ([person.children count] > 0)
    {
        return YES;
    }
    return NO;
}

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
    Person *person = (Person *)item;
    return person.name;
}

它的效果正如我预期的那样:

enter image description here

但是,如果我将 NSOutlineView 更改为 VIEW BASED,情况看起来会非常不同。现在所有名称都被“Table View Cell”替换。我尝试通过返回 NSTableCellView 来解决问题:

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
    Person *person = (Person *)item;

    NSTableCellView *tableCellView = [outlineView makeViewWithIdentifier:@"PersonCell" owner:self];
    tableCellView.textField.stringValue = person.name;

    return tableCellView;
}

如果不做进一步的改变,这不会改变任何东西。当我将 NSOutlineView 中的 TableCellView 的标识符更改为 PersonCell 时,

enter image description here enter image description here

所有单元格最终都是空的。事实上,在outlineView:objectValueForTableColumn:byItem:函数中添加一个简单的NSLog语句表明该函数甚至从未被调用过。

这种方法对我来说适用于标准 NSTableView,并且由于 NSOutlineView 是 NSTableView 的子类,因此我期望这里有相同的行为。

非常感谢任何帮助。

谢谢!

/迈克尔·克努森

objective-c cocoa nstableview nsoutlineview
2个回答
4
投票

我认为为每行返回正确的视图对象的相应方法是

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

而不是

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item

您返回一个视图,而不是基于视图的表视图中的 objectValue。

所以它应该可以使用:

- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
    Person *person = (Person *)item;
    NSTableCellView *tableCellView = [outlineView makeViewWithIdentifier:@"PersonCell" owner:self];
    tableCellView.textField.stringValue = person.name;

    return tableCellView;
}

0
投票

我遇到了这个问题,并意识到我的问题是不理解数据源和委托之间的区别。 数据源方法返回您的内部对象,而不是 NSView 或单元格。然后,委托方法使用 [NSoutlineView makeViewWithIdentifier:owner:] 将它们转换为视图。 所以,我需要实现所有这些事情:

- (NSInteger)outlineView:(NSOutlineView *)outlineView 
      numberOfChildrenOfItem:(nullable id)item 
{
    // if item is nil, that means a top level item
    if( nil == item )
        return myObjectList.count; // not NSViews!!! Whatever your internal data is stored in

    if( NO == [item isKindOfClass: MyObjectType.class] )
        return nil;

    MyObjectType * o = (MyObjectType*) item;
    return o.subitemArray.count;
}

// returns your private objects representing data that will
// will eventually become your views, but we are not returning
// NSViews here yet!  Just internal data objects.
- (id)outlineView:(NSOutlineView *)outlineView 
            child:(NSInteger)index 
           ofItem:(nullable id)item
{
    // if item is nil, that means a top level item
    if( nil == item )
        return myObjectList[index];  // Definitely not a NSView or NSCell

    if( NO == [item isKindOfClass: MyObjectType.class] )
        return nil;

    MyObjectType * o = (MyObjectType*) item;
    return o.subitemArray[index];
}
  • (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item // 不是 NSView 或 NSCell! { if( NO == [item isKindOfClass: MyObjectType.class] ) 返回零;

      MyObjectType * o = (MyObjectType*) item;
      return o.subitemArray.count > 0;
    

    }

  • (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item

© www.soinside.com 2019 - 2024. All rights reserved.