Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSTableView first row initially appears behind the header

I am creating tableView in my application programmatically, and I have this problem:

Whenever the content size of my tableView is bigger than its frame, the first row of tableView appears under the header initially, but it can be easily scrolled back into the position.

The screenshots of what the window looks like after the initial load.

Content size bigger than tableView frame(the issue is here):

enter image description here

Content size smaller than tableView frame(all good here):

enter image description here

My NSViewController class code:

class MainViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource {

let label: NSTextField = {
    let label = NSTextField()
    label.stringValue = "Test App"
    label.font = NSFont.boldSystemFont(ofSize: 14)
    label.textColor = .white
    label.alignment = .center
    label.drawsBackground = false
    label.isBezeled = false
    label.isSelectable = true
    label.isEditable = false
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

let labelContainerView: NSView = {
    let view = NSView()
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

let tableView: NSTableView = {
    let tableView = NSTableView()
    tableView.translatesAutoresizingMaskIntoConstraints = false
    tableView.usesAlternatingRowBackgroundColors = true

    let column = NSTableColumn(identifier: .init(rawValue: "MyColumnID"))
    column.headerCell.title = "Test"
    column.headerCell.alignment = .center
    tableView.addTableColumn(column)

    return tableView
}()

let scrollView: NSScrollView = {
    let scrollView = NSScrollView()
    scrollView.hasVerticalScroller = true
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    return scrollView
}()

override func loadView() {
    view = NSView()
    view.wantsLayer = true
}

var names: [String] = []

override func viewDidLoad() {
    super.viewDidLoad()

    layoutUI()

    for i in 1...9 {
        let name = "Test \(i)"
        names.append(name)
    }

    scrollView.documentView = tableView

    tableView.delegate = self
    tableView.dataSource = self
}



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

    let newCell = MyCellView(identfier: NSUserInterfaceItemIdentifier(rawValue: "MyColumnID"))

    newCell.textView.stringValue = names[row]

    return newCell
}


func numberOfRows(in tableView: NSTableView) -> Int {
    return names.count
}

func layoutUI() {
    view.addSubview(labelContainerView)
    view.addSubview(scrollView)
    labelContainerView.addSubview(label)

    NSLayoutConstraint.activate([
        labelContainerView.topAnchor.constraint(equalTo: view.topAnchor),
        labelContainerView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        labelContainerView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        labelContainerView.heightAnchor.constraint(equalTo: view.heightAnchor,
                                                   multiplier: 1/5),

        label.centerXAnchor.constraint(equalTo: labelContainerView.centerXAnchor),
        label.centerYAnchor.constraint(equalTo: labelContainerView.centerYAnchor,
                                       constant: -4),

        scrollView.heightAnchor.constraint(equalTo: view.heightAnchor,
                                           multiplier: 4/5),
        scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
        scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        ])
}

}

like image 813
anton Avatar asked Sep 01 '25 04:09

anton


1 Answers

I would not recommend to setup a NSTableView in code. Its much easier to do this in Interface Builder and may prevent unwanted side effects. In any case if NSTableView is not displaying the first row as expected I would use scrollToVisible on the related NSScrollView to make the first row visible after loading the data.

like image 94
Marc T. Avatar answered Sep 02 '25 19:09

Marc T.