是否可以纯粹在代码中创建基于视图的NSTableView?

时间:2015-11-30 06:36:09

标签: swift cocoa

我已经在代码中成功创建了基于单元格的NSTableView。我想让单元格更有趣,我已经读过我需要创建一个基于视图的NSTableView。

我的教程如this

我的UI的其余部分完全是代码。我一直试图为这个tableview做同样的事情而没有太多运气。

以下是我如何定义TableView - 我需要停止注册Nib,我不知道如何:

     let nib = NSNib(nibNamed: "TransactionCellView", bundle: NSBundle.mainBundle())
        tableOfTransactions.registerNib(nib!, forIdentifier: "TransactionCellView")

        tableOfTransactions.headerView = nil

        tableOfTransactions.setDelegate(self)
        tableOfTransactions.setDataSource(self)
        tableOfTransactions.reloadData()

以下是每个单元格的存根代码

func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView?{
        var testCell = NSView()
        testCell.frame = NSRect(x: 0, y: 0, width: 300, height: 200)
        return testCell
}

如何实现这一点的任何指示或建议都将非常感谢!

3 个答案:

答案 0 :(得分:7)

-tableView(_:viewForTableColumn:row:)的实现应如下所示:

func tableView(tableView: NSTableView,
    viewForTableColumn
    tableColumn: NSTableColumn?,
    row: Int) -> NSView? {

        var retval: NSView?
        if let spareView = tableView.makeViewWithIdentifier("CodeCreatedTableCellView",
            owner: self) as? NSTableCellView {

            // We can use an old cell - no need to do anything.
            retval = spareView

        } else {

            // Create a text field for the cell
            let textField = NSTextField()
            textField.backgroundColor = NSColor.clearColor()
            textField.translatesAutoresizingMaskIntoConstraints = false
            textField.bordered = false
            textField.controlSize = NSControlSize.SmallControlSize

            // Create a cell
            let newCell = NSTableCellView()
            newCell.identifier = "CodeCreatedTableCellView"
            newCell.addSubview(textField)
            newCell.textField = textField

            // Constrain the text field within the cell
            newCell.addConstraints(
                NSLayoutConstraint.constraintsWithVisualFormat("H:|[textField]|",
                    options: [],
                    metrics: nil,
                    views: ["textField" : textField]))

            newCell.addConstraints(
                NSLayoutConstraint.constraintsWithVisualFormat("V:|[textField]|",
                    options: [],
                    metrics: nil,
                    views: ["textField" : textField]))

            textField.bind(NSValueBinding,
                toObject: newCell,
                withKeyPath: "objectValue",
                options: nil)

            retval = newCell
        }

        return retval
}

如果您的表包含数百行,Cocoa将尝试重用已创建的视图,但不再显示在屏幕上。此代码段的第一部分使用NSTableView方法查找此类视图。如果找不到,则需要从头开始创建一个。

如果您没有理由不这样做,则应使用NSTableCellView的实例(或子类)作为您的观点。它并没有给NSView增加太多,但它的一个关键特性是它保留了对视图所代表的模型的引用(由-tableView(_:objectValueForTableColumnRow:row:)设置)。在此示例中,我使用此功能使用绑定设置文本字段的字符串值。

另一点需要注意的是,您应该为视图提供一个标识符,该标识符与您为视图所在的NSTableColumn提供的标识符相匹配。这样做可以使您的表视图使用上面讨论的可重用视图功能。

答案 1 :(得分:1)

这在我尝试对没有IB和Nibs的滚动表进行编程时非常有用。这是我的玩具版本,已更新为Swift 4.2。

自定义单元格视图子类仅在这里让我看到单元格实际上已被重复使用,

    import Cocoa

    class DIYTableViewDataSource: NSObject, NSTableViewDataSource {

        func numberOfRows(in tableView: NSTableView) -> Int {
            return 25
        }
    }

    class CustomTableCellView: NSTableCellView {
        var count = 1
    }

    func createCell(_ id: NSUserInterfaceItemIdentifier) -> CustomTableCellView {
        // Create a text field for the cell
        let textField = NSTextField()
        textField.backgroundColor = NSColor.clear
        textField.translatesAutoresizingMaskIntoConstraints = false
        textField.isBordered = false

        // Create a cell
        let cell = CustomTableCellView() // Doing this to see that cells get re-used
        cell.identifier = id
        cell.addSubview(textField)
        cell.textField = textField

        // Constrain the text field within the cell
        textField.widthAnchor.constraint(equalTo: cell.widthAnchor).isActive = true
        textField.heightAnchor.constraint(equalTo: cell.heightAnchor).isActive = true

        textField.bind(NSBindingName.value, to: cell, withKeyPath: "objectValue", options: nil)

        return cell
    }

    class DIYTableViewDelegate: NSObject, NSTableViewDelegate {

         func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
             let id = tableColumn!.identifier
             var view = tableView.makeView(withIdentifier: id, owner: nil) as? CustomTableCellView
             if view == nil {
                 view = createCell(id)
             }
             view!.textField!.stringValue = "\(id.rawValue) \(row) \(view!.count)"
             view!.count += 1

             return view
         }
     }

答案 2 :(得分:0)

斯威夫特 5

你需要实现 NSTableView 的委托方法。无需注册任何nib文件?

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
    let view = CustomView()
    view.configure(with: row)
    return view
}

只需创建自定义视图的实例(NSView 的子类)。 它看起来像这样:

class CustomView: NSView {

private let label = NSTextField()

override init(frame frameRect: NSRect) {
    super.init(frame: frameRect)
    setupView()
}

required init?(coder: NSCoder) {
    fatalError("init coder has not been implemented")
}

func setupView() {
    self.addSubview(label)
    label.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        label.topAnchor.constraint(equalTo: self.topAnchor, constant: 8),
        label.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 8),
        label.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 8),
        label.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 8)
    ])
}

func configure(with row: Int) {
    label.stringValue = String(describing: row + 1)
}

}