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

swift - Swift中基于 View 的NSTableView不显示内容-LMLPHP

这是代码:

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
    }
}


还有一些注意事项:在情节提要中,我确实为视图控制器的dataSourcedelegate创建了出口。我的前两列的标识符设置为“ fileCol”和“ titleCol”。该项目将编译并运行,而不会出现任何错误或警告。以下是我的故事板的一些屏幕截图。

swift - Swift中基于 View 的NSTableView不显示内容-LMLPHP

swift - Swift中基于 View 的NSTableView不显示内容-LMLPHP

最佳答案

看来您混淆了两种不同的方法。数据源方法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"
}


请注意,它不会尝试创建或返回视图。

那是第一步。表格视图将使用您从该方法返回的对象值,并将其分配给用作单元格视图的objectValueNSTableCellView属性。但是,就其本身而言,这无能为力。

有几种方法可以使该对象值实际显示在单元格视图中:


不要使用每个都包含文本字段的NSTableCellView作为单元格视图,而应使用文本字段本身。由于NSTextField也具有objectValue属性(从NSControl继承),因此表视图可以在该属性上设置对象值,然后显示您的内容。缺点是您的单元格视图只是一个视图。如果您想在每个单元格中使用多个视图,则不能使用此方法。
像现在一样,继续使用NSTableCellView作为单元格视图。使用键路径NSTableCellView将文本字段的Value绑定绑定到包含的objectValue。这样,当表设置objectValueNSTableCellView时,它将自动传播到文本字段。
通过直接设置文本字段属性的值,实现tableView(_:viewForTableColumn:row:)以配置单元格视图。基本上,这看起来像是您为tableView(_:objectValueForTableColumn:row:)实现的主体。这有效地使tableView(_:objectValueForTableColumn:row:)的实现变得多余。您需要实现它,并且表视图将调用它并使用结果来设置单元格视图的objectValue,但这不会对单元格视图中的文本字段产生影响。
使用NSTableCellView的自定义子类,它将didSet属性观察者添加到objectValue属性。这样可以将新值适当地转发到子视图。


我个人使用绑定方法。

另外,您应该考虑从fileData返回整个tableView(_:objectValueForTableColumn:row:)对象,而不是返回其属性之一的值。因此,tableView(_:objectValueForTableColumn:row:)对列仅对行不敏感。每个objectValueNSTableCellView将是对应的FilesListData实例。

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

如果您的单元格视图最终在其中包含多个视图时变得更加复杂,这将特别有用。每个视图都可以访问FilesListData对象的任何属性。使用当前仅返回一个属性作为单元格对象值的方法,视图将只能使用该值。

关于swift - Swift中基于 View 的NSTableView不显示内容,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32315262/

10-10 11:52