我试图在基于视图的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
创建了出口。我的前两列的标识符设置为“ fileCol”和“ titleCol”。该项目将编译并运行,而不会出现任何错误或警告。以下是我的故事板的一些屏幕截图。最佳答案
看来您混淆了两种不同的方法。数据源方法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
的NSTableCellView
属性。但是,就其本身而言,这无能为力。有几种方法可以使该对象值实际显示在单元格视图中:
不要使用每个都包含文本字段的
NSTableCellView
作为单元格视图,而应使用文本字段本身。由于NSTextField
也具有objectValue
属性(从NSControl
继承),因此表视图可以在该属性上设置对象值,然后显示您的内容。缺点是您的单元格视图只是一个视图。如果您想在每个单元格中使用多个视图,则不能使用此方法。像现在一样,继续使用
NSTableCellView
作为单元格视图。使用键路径NSTableCellView
将文本字段的Value绑定绑定到包含的objectValue
。这样,当表设置objectValue
的NSTableCellView
时,它将自动传播到文本字段。通过直接设置文本字段属性的值,实现
tableView(_:viewForTableColumn:row:)
以配置单元格视图。基本上,这看起来像是您为tableView(_:objectValueForTableColumn:row:)
实现的主体。这有效地使tableView(_:objectValueForTableColumn:row:)
的实现变得多余。您需要实现它,并且表视图将调用它并使用结果来设置单元格视图的objectValue
,但这不会对单元格视图中的文本字段产生影响。使用
NSTableCellView
的自定义子类,它将didSet
属性观察者添加到objectValue
属性。这样可以将新值适当地转发到子视图。我个人使用绑定方法。
另外,您应该考虑从
fileData
返回整个tableView(_:objectValueForTableColumn:row:)
对象,而不是返回其属性之一的值。因此,tableView(_:objectValueForTableColumn:row:)
对列仅对行不敏感。每个objectValue
的NSTableCellView
将是对应的FilesListData
实例。然后,将调整文本字段与其包围的单元格视图的绑定,以选择
FilesListData
的适当属性。例如,一栏中的文本字段将使用键路径NSTableCellView
绑定到其封闭的objectValue.file
。在另一列中,它将使用objectValue.title
的关键路径。如果您的单元格视图最终在其中包含多个视图时变得更加复杂,这将特别有用。每个视图都可以访问
FilesListData
对象的任何属性。使用当前仅返回一个属性作为单元格对象值的方法,视图将只能使用该值。关于swift - Swift中基于 View 的NSTableView不显示内容,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32315262/