2015-08-31 41 views
0

我试图在基于视图的NSTableView中显示非常基本的数据结构。经过几个小时的搜索,我终于得到了大部分桌子的设置点。行数是正确的,我知道func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn?, row: Int)方法为所有单元执行,因为它在控制台中输出正确的数据。不幸的是,表格显示的是默认值,而不是我的数据数组中的String在Swift中基于视图的NSTableView不显示内容

The table view doesn't display the correct data

下面的代码:

ViewController.swift

import Cocoa 

class ViewController: NSViewController { 

    @IBOutlet weak var myTableView: NSTableView! 
    var files = [FilesListData]() 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.setupSampleFiles() 
    } 
    override func viewDidAppear() { 
     super.viewDidAppear() 
    } 

    func setupSampleFiles() { 
     let file1 = FilesListData(file: "test.mp3", title: "test") 
     let file2 = FilesListData(file: "test2.mp3", title: "test 2") 

     self.files = [file1, file2] 
    } 
} 

extension ViewController: NSTableViewDataSource { 
    func numberOfRowsInTableView(tableView: NSTableView) -> Int { 
     return self.files.count 
    } 

    func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn?, row: Int) -> AnyObject? { 
     let cellView: NSTableCellView = tableView.makeViewWithIdentifier((tableColumn!.identifier), owner: self) as! NSTableCellView 

     let fileData = self.files[row] 
     if tableColumn!.identifier == "fileCol" { 
      cellView.textField!.stringValue = fileData.file 
     } else if tableColumn!.identifier == "titleCol" { 
      cellView.textField!.stringValue = fileData.title 
     } else { 
      cellView.textField!.stringValue = "N/A" 
     } 
     return cellView 
    } 
} 

extension ViewController: NSTableViewDelegate { 
} 

FilesListData.swift

import Foundation 

class FilesListData: NSObject { 
    var file: String 
    var title: String 

    override init() { 
     self.file = String() 
     self.title = String() 
    } 

    init(file: String, title: String) { 
     self.file = file 
     self.title = title 
    } 
} 

一些更多的注意事项:在故事板,我也创建dataSource和的插座3210添加到View Controller。我的前两列的标识符被设置为“fileCol”和“titleCol”。该项目编译并运行时没有任何错误或警告。以下是我的故事板的几个截图。

Objects tree

Identifier for the first column

回答

1

看起来你已经混了两种不同的方法。 数据源方法tableView(_:objectValueForTableColumn:row:)用于返回数据对象,而不是单元格视图。 代表方法tableView(_:viewForTableColumn:row:)用于返回单元格视图,可能配置了适合列和行的数据。

所以,你可能重写前者如:

func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn?, row: Int) -> AnyObject? { 
    let fileData = self.files[row] 
    if tableColumn!.identifier == "fileCol" { 
     return fileData.file 
    } else if tableColumn!.identifier == "titleCol" { 
     return fileData.title 
    } 

    return "N/A" 
} 

注意,它并不试图创建或返回一个视图。

这是第一步。表视图将采用您从该方法返回的对象值,并将其分配给您用作单元视图的NSTableCellViewobjectValue属性。然而,它本身并没有做任何事情。

有几种不同的方法才能让该对象的值在你的意见,实际显示:

  • 而不是使用NSTableCellView S,每个都包含一个文本框,因为你的意见,使用一个文本字段本身。由于NSTextField也有objectValue属性(从NSControl继承),因此表视图可以在其上设置对象值,并显示您的内容。缺点是你的单元格视图只是一个视图。如果你想在每个单元格中看到多个视图,就不能使用这种方法。
  • 继续使用NSTableCellView作为你的单元格视图,就像你现在正在做的那样。将文本字段的值绑定绑定到包含NSTableCellView的关键路径objectValue。这样,当表格设置NSTableCellViewobjectValue时,它会自动传播到文本字段。
  • 实施tableView(_:viewForTableColumn:row:)通过直接设置文本字段属性的值来配置单元格视图。基本上,这看起来像是你为tableView(_:objectValueForTableColumn:row:)实施的主体。这有效地使您的执行tableView(_:objectValueForTableColumn:row:)冗余。您需要实现它,表视图将调用它并使用结果来设置单元格视图的objectValue,但这对单元格视图内的文本字段没有影响。
  • 使用NSTableCellView的自定义子类,它将didSet属性观察者添加到objectValue属性。这可以将新的价值适当地转发给子视图。

就我个人而言,我使用绑定方法。

另外,您应该考虑从tableView(_:objectValueForTableColumn:row:)返回整个fileData对象,而不是其某个属性的值。所以,tableView(_:objectValueForTableColumn:row:)不会对列,只有行敏感。每个NSTableCellViewobjectValue将是相应的FilesListData实例。

然后,将调整文本字段与其封闭单元格视图的绑定,以选择FilesListData的相应属性。例如,一列中的文本字段将被绑定到其包含NSTableCellView的关键路径objectValue.file。在另一列中,它将使用关键路径objectValue.title

如果您的单元格视图最终变得更加复杂并且其中包含多个视图,那么这将特别有用。每个视图都可以访问FilesListData对象的任何属性。使用目前的方法只返回单个属性作为单元格的对象值,那么视图就会停留在仅使用该值的状态。

+0

你好肯和谢谢你的彻底答案。我想保留'NSTableCellView's,因为正如你所提到的那样,我将能够在后面扩展表格的复杂性。我能够通过实现'tableView(_:viewForTableColumn:row:)'成功显示数据。然而,绑定方法似乎很有趣,但我不知道如何实现这一点。你提到的“价值”就是'委托'出口? N.B .:我没有提到的一件事是我的'NSTableCellView'的'textField'有一个到它的子节点'NSTextField'的插座。 – beeb

+0

设置绑定的最简单方法是在IB中。选择文本字段后,选择视图>实用程序>显示绑定检查器。切换打开值绑定。对于“绑定到”弹出窗口,请选择表格单元格视图。对于模型关键路径输入'objectValue.file'或类似的东西。 (Xcode会显示一个感叹号图标,因为它无法验证关键路径是否有效,但是您可以忽略它。这是系统的动态性质,因为它无法知道'objectValue'类型是什么类型。) –

+0

精彩,这就像一个魅力!再次感谢 – beeb

相关问题