4

I have a custom table cell which contains a number of UILabels. At runtime, I am adjusting the height of the labels to fit their contents using sizeWithFont:constrainedToSize:lineBreakMode: and repositioning them accordingly. The last label in the cell contains a large amount of text, causing it to wrap, and I'm having a very odd problem. Although the sizeWithFont call returns the correct size, and I'm setting the UILabel's frame to that height, it draws a couple of lines short. This screenshot illustrates what I'm talking about:

Screenshot of UILabel problem

In this example, the height of the full block of text should be 90 (as checked in Interface Builder), and that's what returns from sizeWithFont. It's also the height that the UILabel's frame is set to, which I have verified by logging and also by stopping execution and inspecting the value. However, as you can see, it's clearly not drawing the full 90 pixels high, although it's correctly allocating the space for it (the thin black line above 'Edited' is the table cell border). I'm completely perplexed. If anyone can offer some insight as to why it's behaving this way, I would be very grateful.

Community
  • 1
  • 1
Tim Keating
  • 5,636
  • 4
  • 41
  • 51
  • Progress: this happens because the height of the cell as set in IB is taller than the actual height returned by heightForRowAtIndexPath. When the cell is crunched down, it appears some clipping of the bottom-most UILabel is happening as well. – Tim Keating Oct 14 '09 at 06:55
  • See my answer on the [same topic](http://stackoverflow.com/questions/129502/how-do-i-wrap-text-in-a-uitableviewcell-without-a-custom-cell/905565#905565). – Tim Rupe Oct 06 '09 at 17:18
  • That answer outlines very nicely all the things I'm already doing :-) – Tim Keating Oct 06 '09 at 19:43

3 Answers3

7

At last, a solution!

Turns out that the cell does layout twice -- once during heightForRowAtIndexPath, which is where I tweak all the heights of the subviews and the cell, and later during some untraceable transaction originating in __CFRunLoopDoObservers. How did I trace this? I added a layoutSubviews override to my custom table view cell class so I could breakpoint it.

During the second pass, the last UILabel subview was getting set to a shorter height than I set it to, probably in accordance with some arcane autoresizing rules. (Yes, I tried tweaking all of those settings first, with no success.) As it turns out, merely doing nothing in layoutSubviews disabled this framework behavior, allowing me to completely control how my views draw.

Tim Keating
  • 5,636
  • 4
  • 41
  • 51
1

With iOS 8 it doesn't work anymore like this. Implementing layoutSubviews alone doesn't do the trick, because the layout of subviews have already changed when the method is called.

I have found 2 solutions:

  1. adding NSLayoutConstraint to layout the subviews programmatically
  2. implementing subview's layoutSubviews and change the frame

An example für solution 2:

- (void)layoutSubviews
{
    [super layoutSubviews];

    CGRect frame = self.frame;
    frame.size.height = 39.f;
    self.frame = frame;
}
Hans One
  • 3,079
  • 24
  • 28
0

I've fought with similar problems. It was to do with other properties being set in previous incarnations of the cell. To find it / prove it I changed the reuseidentifer for the offending cell to make sure it was a unique cell.

Andiih
  • 11,749
  • 9
  • 54
  • 87