Ravi Ravi - 5 months ago 64
Swift Question

NSTableView: replace empty table with image

When I don't have any rows to display in my NSTableView, I'd like to display an image instead. I tried the following in my custom NSViewController class, but I still see an empty table. I have "ic_empty_image" in Assets.xcassets.

func numberOfRowsInTableView(tableView: NSTableView) -> Int {
if model.numRows == 0 {
let image = NSImage(named: "ic_empty_image")
let imageView = NSImageView()
imageView.image = image
self.view.replaceSubview(tableView, with: imageView)
self.view.setNeedsDisplayInRect(imageView.visibleRect)
} else {
return model.numRows
}
}

Answer

If you take advantage of view based table, you can just flip view for the cell when you know you have empty data set. The trick is to bind you table to the array and instead of having it empty just have one item - indicator.

I created sample project for you here: https://github.com/emankovski/nstableview-empty-picture

But general logic is actually pretty simple: I created NSTableCellView object in nib and just return it when I see the indicator of no data. Note that I also change row height for table view as my cell with image way taller than cells with text. I hope it helps.

 class AppDelegate: NSObject, NSApplicationDelegate, NSTableViewDataSource {

private static let placeholder = "<Placeholder>"
dynamic var items = [String]()

@IBOutlet weak var window: NSWindow!
@IBOutlet weak var tableView: NSTableView!
@IBOutlet weak var imageCell: NSTableCellView!

@IBAction func addRowsPressed(sender: AnyObject) {
    appendItems()
}

@IBAction func clearTablePressed(sender: AnyObject) {
    removeItems()

}

func applicationDidFinishLaunching(aNotification: NSNotification) {
    appendItems()

}

func applicationWillTerminate(aNotification: NSNotification) {
    // Insert code here to tear down your application
}

func appendItems() {


    items.removeAll()

    items.append("One")
    items.append("Two")
    items.append("Three")

    tableView.rowHeight = 20

}

func removeItems() {

    items.removeAll()
    tableView.rowHeight = 50
    items.append(AppDelegate.placeholder)


}

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

    if items[row] == AppDelegate.placeholder {

        return imageCell
    }

    let cellView = tableView.makeViewWithIdentifier("CellView", owner: nil) as! NSTableCellView

    return cellView
}


 }

UPDATE for storyboards: Picture of how to drag table cell view to view controller in storyboards:

enter image description here

Then just create outlet and connect-drag that object to that outlet:

  @IBOutlet var tableCellView: NSTableCellView!