I have an NSImageCell
table column whose valuePath
is bound to a path supplied by my object through an NSArrayController
.
My NSTableViewDelegate
implements the -tableView:heightOfRow:
method, in order to have variable row height. I need to calculate row height based on the dimensions of the image displayed in the aforementioned column.
Right now, I'm getting horrible performance, though, since I'm calling [[NSImage alloc] initWithContentsOfFile:<path>]
for each iteration. Is there any way to load the image representation that each NSImageCell
has already retrieved for display?
I'm happy with the performance exhibited by using the valuePath
binding, and would rather not cache each image on my own, as there will be many of them, each somewhat large.
I tried the NSTableColumn
method -dataCellForRow:
, which sounded perfect, except the cell returned returns an objectValue
that seems to be the last row for which data was loaded.
Update (solution, unsatisfactory)
I figured out an approximate solution (posted simultaneously below), but it seems clumsy (and I've already seen it fail at random, irreproducible times), and I am still looking for a better solution.
I'm using the -tableView:willDisplayCell:forTableColumn:row:
delegate method to populate a mutable dictionary with [[cell objectValue] size]
(the image's size) keyed to the represented object's unique ID. Then, in the -tableView:heightOfRow:
call I'm looking up the cover from this dictionary. I need to call [tableView noteNumberOfRowsChanged]
after data is loaded, otherwise the dictionary isn't filled properly for the initial screen of data.
I tried the NSTableColumn method -dataCellForRow:, which sounded perfect, except the cell returned returns an objectValue that seems to be the last row for which data was loaded.
That's because the NSTableColumn
only uses a single data cell for displaying the entire column, swapping out its value as it draws.
If I were you, I would probably try implementing the – tableView:willDisplayCell:forTableColumn:row:
method in your NSTableViewDelegate
. Then you can intercept the cell before it's about to be drawn, get its value at that moment, and cache just its height (as an NSNumber*
or CGFloat
). Then you can return that value in -tableView:heightOfRow:
.
Then again, it's possible that -tableView:heightOfRow:
gets called before – tableView:willDisplayCell:forTableColumn:row:
, so that might not work. I'm not sure. But that's where I would start.