我试图在基于视图的NSTableView中显示非常基本的数据结构。经过几个小时的搜索,我终于达到了大部分桌面设置的地步。行数是正确的,我知道所有单元格都执行func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn?, row: Int)
方法,因为它在控制台中输出了正确的数据。不幸的是,该表显示的是默认值,而不是我的数据数组中的String
。
以下是代码:
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
和delegate
的插座。我的前2列的标识符设置为" fileCol"和" titleCol"。项目编译并运行时没有任何错误或警告。以下是我的故事板的一些截图。
答案 0 :(得分: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"
}
请注意,它不会尝试创建或返回视图。
这是第一步。表视图将获取您从该方法返回的对象值,并将其分配给您用作单元格视图的objectValue
的{{1}}属性。但是,它本身并没有做任何事情。
有几种不同的方法可以让对象值实际显示在单元格视图中:
NSTableCellView
,每个包含文本字段作为单元格视图。由于NSTableCellView
还具有NSTextField
属性(继承自objectValue
),因此表格视图可以设置对象值,并显示您的内容。缺点是您的单元格视图只是一个视图。如果您希望在每个单元格中看到多个视图,则无法使用此方法。NSControl
作为您的单元格视图,就像您现在所做的那样。使用关键路径NSTableCellView
将文本字段的值绑定绑定到包含NSTableCellView
的值。这样,当表格设置objectValue
的{{1}}时,它会自动传播到文本字段。objectValue
以配置单元格视图。基本上,这看起来就像你为NSTableCellView
实施的内容。这有效地使您tableView(_:viewForTableColumn:row:)
的实现变得多余。您需要实现它,表视图将调用它并使用结果来设置单元格视图的tableView(_:objectValueForTableColumn:row:)
,但这对单元格视图中的文本字段没有影响。tableView(_:objectValueForTableColumn:row:)
的自定义子类,将objectValue
属性观察者添加到NSTableCellView
属性。这可以将新值转发给子视图。就个人而言,我使用绑定方法。
此外,您应该考虑从didSet
返回整个objectValue
对象,而不是其中一个属性的值。因此,fileData
对列不敏感,只对行敏感。每个tableView(_:objectValueForTableColumn:row:)
的{{1}}将是相应的tableView(_:objectValueForTableColumn:row:)
个实例。
然后,将调整文本字段与其封闭单元格视图的绑定,以选择objectValue
的相应属性。例如,一列中的文本字段将绑定到其封闭的NSTableCellView
,其关键路径为FilesListData
。在另一列中,它将使用FilesListData
的关键路径。
如果您的单元格视图最终会在其中包含多个视图时变得更加复杂,这将非常有用。每个视图都可以访问NSTableCellView
对象的任何属性。使用当前只返回单个属性作为单元格对象值的方法,那么视图就只能处理这一个值。