I have an NSTableView with some cells that where the value of enabled is set through bindings. I want to be able to change the colour of the cells depending on whether the cell is enabled or not. Previously I have done this through the NSTAbleView delegate method tableView: willDisplayCell: forTableColumn: row: which up until now worked fine. I've had to switch off the table delegate though and so I need to find another way to do it. I suspect it's a problem with an obvious answer, but how do I access each cell in the table? I can get the number of rows and columns in the table, and I can cycle trough them, I'm just not sure what method to call to get the cell in column i, row j.
Objective-c – Accessing a specific cell in an NSTableView
cocoaobjective c
Related Solutions
This is a chicken and the egg problem. The table needs to know the row height because that determines where a given view will lie. But you want a view to already be around so you can use it to figure out the row height. So, which comes first?
The answer is to keep an extra NSTableCellView
(or whatever view you are using as your "cell view") around just for measuring the height of the view. In the tableView:heightOfRow:
delegate method, access your model for 'row' and set the objectValue
on NSTableCellView
. Then set the view's width to be your table's width, and (however you want to do it) figure out the required height for that view. Return that value.
Don't call noteHeightOfRowsWithIndexesChanged:
from in the delegate method tableView:heightOfRow:
or viewForTableColumn:row:
! That is bad, and will cause mega-trouble.
To dynamically update the height, then what you should do is respond to the text changing (via the target/action) and recalculate your computed height of that view. Now, don't dynamically change the NSTableCellView
's height (or whatever view you are using as your "cell view"). The table must control that view's frame, and you will be fighting the tableview if you try to set it. Instead, in your target/action for the text field where you computed the height, call noteHeightOfRowsWithIndexesChanged:
, which will let the table resize that individual row. Assuming you have your autoresizing mask setup right on subviews (i.e.: subviews of the NSTableCellView
), things should resize fine! If not, first work on the resizing mask of the subviews to get things right with variable row heights.
Don't forget that noteHeightOfRowsWithIndexesChanged:
animates by default. To make it not animate:
[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:0];
[tableView noteHeightOfRowsWithIndexesChanged:indexSet];
[NSAnimationContext endGrouping];
PS: I respond more to questions posted on the Apple Dev Forums than stack overflow.
PSS: I wrote the view based NSTableView
Just change the Content Mode
to Cell Based
for the table view in IB. IB will display Text Cell
as the cell placeholders, which are populated at runtime by whatever you return from tableView:objectValueForTableColumn:row:
Best Answer
Generally speaking, you shouldn't be cycling through the rows and columns. Your code should be able to do the right thing, given any row or column.
One way to do it is to write your own cell class and implement the appropriate drawing and highlighting methods that you'll find in the NSCell documentation. You'd implement
– drawWithFrame:inView:
and probably-highlight:withFrame:inView:
Yet another way is to subclass
NSTableView
, and override-preparedCellAtColumn:row:
to do whatever manipulation of the cell you want just before it's drawn.The easiest way to do what you want though, is to just use the delegate method as you were before. Why don't you want to do it that way?