使用默认方法扩展 NSTableViewDataSource 协议

Extending the NSTableViewDataSource Protocol with a default method

我想向 NSTableViewDataSource 协议添加一个默认方法。但是当我这样做时,默认值总是被调用,即使该方法是在实际数据源中定义的。具体来说:

我有一个单列的 NSTableView,它可以在不同的时间采用多个不同的数据源。在一种情况下,我希望数据源不仅能够提供显示的值,而且能够提供 table 中行的背景颜色。在其他情况下,table 可以是单一颜色。我的想法是先扩展 NSTableViewDataSource 协议:

extension NSTableViewDataSource
  { 
    func tableView (tableView: NSTableView, colorIndexForRow row: Int) -> Int
      { 
        return 0 
      }
  }

然后在 table 代表中我把这个:

public func tableView (tableView: NSTableView, didAddRowView rowView: NSTableRowView, forRow row: Int)
  { 
    let colorIndex = tableView.dataSource()!.tableView(tableView, colorIndexForRow: row)
    rowView.backgroundColor = rowColors[colorIndex]
  }

(rowColors 只是一个 NSColor 对象数组,六个用于实验目的。)

最后,我的实验数据源是这样的:

public func numberOfRowsInTableView (tableView: NSTableView)  -> Int
  { 
    return 100
  }

public func tableView (tableView: NSTableView, objectValueForTableColumn column: NSTableColumn?, row: Int) -> AnyObject?
  { 
    return String(format: "This is row %3i", row)   
  }

public func tableView (tableView:  NSTableView, colorIndexForRow row: Int) -> Int
  { 
    return row % 6    
  }

我预计这会产生一个 table,其中行处于六种颜色的旋转循环中。我实际得到的是一个 table,颜色均为 rowColors[0]。始终调用我的 colorIndexForRow 方法的默认值,即使我在数据源中提供了该方法。我对 Swift 文档的阅读是,协议扩展中的默认值应该仅在实际方法不存在时才被调用。谁能告诉我我做错了什么?

原因是协议扩展

您可以将函数重写为:

public func tableView (tableView: NSTableView, didAddRowView rowView: NSTableRowView, forRow row: Int)
{ 
    let colorIndex = self.tableView(tableView, colorIndexForRow: row)
    rowView.backgroundColor = rowColors[colorIndex]
}

我决定采取不同的策略:我简单的单一功能需求并不能证明处理静态与动态调度问题是合理的。我没有扩展 NSTableViewDataSource,而是定义了一个继承的协议:

public  protocol        ColorTableViewDataSource: NSTableViewDataSource
  { 
    func tableView (tableView: NSTableView, colorIndexForRow row: Int) -> Int
  }

然后我的委托函数测试一致性:

public func tableView (tableView: NSTableView, didAddRowView rowView: NSTableRowView, forRow row: Int)
  {
    if  let dataSource = tableView.dataSource() as? ColorTableViewDataSource
      {
        rowView.backgroundColor = rowColors[dataSource.tableView(tableView, colorIndexForRow: row)]
      }
  }

我的数据源函数完全没有变化。当我想要彩色行时,我只是声明符合新协议的数据源对象。它似乎完全符合我的要求。