Reputation: 2913
After searching through SO and online, I'm struggling to figure out a concept that I thought would be relatively simple. Essentially, I have a table in an OS X Swift app, with several columns, and it is currently populating data. I am trying to discern how I can set the background color of each "row" (ideally with alternating colors, but I'll start with just one color). My MasterViewController file is like so;
import Cocoa
class MasterViewController: NSViewController {
var minions = [Minion]()
func setupSampleMinion() {
minions = Minion.fetchMinionData()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
}
}
// MARK: - NSTableViewDataSource extension MasterViewController: NSTableViewDataSource {
func numberOfRowsInTableView(aTableView: NSTableView) -> Int {
return self.minions.count
}
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
// 1
var cellView: NSTableCellView = tableView.makeViewWithIdentifier(tableColumn!.identifier, owner: self) as! NSTableCellView
let minion = self.minions[row]
// 2
if tableColumn!.identifier == "MyColumn" {
// 3
cellView.imageView!.image = NSImage(named: "minion.name!")
cellView.textField!.stringValue = minion.name!
return cellView
}
return cellView
}
}
func tableView(tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
let myCustomView = MyRowView()
return myCustomView
}
class MyRowView: NSTableRowView {
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
self.backgroundColor = NSColor(red: 0.76, green: 0.82, blue: 0.92, alpha: 1)
NSRectFill(dirtyRect)
}
}
// MARK: - NSTableViewDelegate extension MasterViewController: NSTableViewDelegate {
}
While I THINK I have some of the coding right, this does not seem to set the background color if the row in any way. Any thoughts or overall guidance would be most appreciated. Thank you!
Upvotes: 2
Views: 2513
Reputation: 90701
If you just want the rows to use the standard alternating colors for rows, there's a simple checkbox in the Attributes inspector for the table view in IB to enable that.
To use a non-standard background color, you want to set the row view's backgroundColor
, but not inside of drawRect()
. If you change properties of a view that affect how it draws inside of drawRect()
, that will probably mark the view as needing display, which will provoke another call to drawRect()
, etc.
It should work to just set it in the delegate's tableView(_:didAddRowView:forRow:)
method. That's documented in the description of the backgroundColor
property.
With regard to your attempt at overriding drawRect()
: setting the row view's backgroundColor
will presumably affect how the superclass draws. So, setting it after calling through to super is unlikely to help. It definitely won't affect the subsequent NSRectFill()
call. That function relies on the fill color set for the current graphics context, which is implicit. You would change that by calling someColor.set()
.
Buy, anyway, there should be no need to override drawRect()
given that you can set the backgroundColor
. If you want to achieve some background drawing beyond what's possible by just setting a color, you should override drawBackgroundInRect()
and not drawRect()
, anyway.
Finally, your implementation of tableView(tableView:rowViewForRow:)
should call the table view's makeViewWithIdentifier(_:owner:)
method first, before creating a new view. And it should set the identifier on any new view it does create. That allows the table view to maintain a reuse queue of views, to avoid constantly destroying and recreating views.
Upvotes: 2