更新:链接到完整源代码(下载)
我正在尝试实现基于视图的 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;
}
它的效果正如我预期的那样:
但是,如果我将 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 时,
所有单元格最终都是空的。事实上,在outlineView:objectValueForTableColumn:byItem:函数中添加一个简单的NSLog语句表明该函数甚至从未被调用过。
这种方法对我来说适用于标准 NSTableView,并且由于 NSOutlineView 是 NSTableView 的子类,因此我期望这里有相同的行为。
非常感谢任何帮助。
谢谢!
/迈克尔·克努森
我认为为每行返回正确的视图对象的相应方法是
- (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;
}
我遇到了这个问题,并意识到我的问题是不理解数据源和委托之间的区别。 数据源方法返回您的内部对象,而不是 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