Getting table view text cell to resize so wrapping text is visible

I’m trying to get my table view to display wrapped text properly. It doesn’t matter how big I make my rows because the text cell within the row doesn’t resize to accommodate additional lines of text when it wraps. The cell is always centered vertically in the row and a set size.

The table is built and populated following the example in AppleScriptObjC Explored.
Please let me know what else you might need to know about it.


Are you using a xib, or doing it programmatically? One thing to check is that the text label/frame you are using is set to word or character wrap, perhaps it’s turned off, or you didn’t program it to wrap?

I have a window in my MainMenu.xib, with a Table View, which is bound to an Array Controller. In the Attributes Inspector I have the Text Field Cell set to Text Direction Natural, Layout Left to Right, Line Break Word Wrap.

It does wrap the text as expected, but it disappears below the first line. I can read it if I select it and arrow down because it scrolls. It doesn’t matter what I set the row height to because the height of the Text Cell within the row is fixed at one line. I don’t see any way to change that.

What you want to do is far from simple. You need to implement the NSTableViewDelegate method -tableView:heightOfRow:. Within that, you need to calculate the needed height for the row.

There are a couple of ways to calculate how much space is needed for text. You can create a dummy text container and layout the text there, getting its used rectangle. This snippet will give you some idea of how to do that:

set theText to "Fee, fi, fo, fum"
set ts to current application's NSTextStorage's alloc()'s initWithString_(theText)
set tc to current application's NSTextContainer's alloc()'s initWithContainerSize_({200, 10000}) -- width should match cell width
set lm to current application's NSLayoutManager's alloc()'s init()
tell lm to addTextContainer_(tc)
tell ts to addLayoutManager_(lm)
tell ts to addAttribute_value_range_(current application's NSFontAttributeName, current application's NSFont's fontWithName_size_("Helvetica", 24), {0, theText's length})
lm's glyphRangeForTextContainer_(tc)
lm's usedRectForTextContainer_(tc)

I suspect it can be done more efficiently by getting the field editor for the cell, and asking its layout manager for usedRectForTextContainer:, but I’m not really sure how.

In any case, tableView:heightOfRow: will be called a lot, so slow code is going to slow down your table. And this is likely to be slow code.

If possible, you might want to consider other approaches, like having a separate text field that shows the contents of the long cell of the selected row.

Wow - thanks Shane. I was thinking about doing the separate text field but it seemed like an awkward work-around for something that should be obvious and simple, and is even apparently (though not actually) accommodated right there in IB with the “Word Wrap” setting. But I think I’ll go that route.