Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why self.frame and self.contentView.frame often differs for UITableViewCell?

I sprinkled

NSAssert(abs(self.frame.size.height-self.contentView.frame.size.height)<=1,@"Should be the same");

on various places when creating a UITableViewCell to return.

The result often differs. Sometimes by 1 pixel, sometimes by 2.

I wonder what's the problem is? Is there someting in cellForRowAtIndexPath that makes them different?

They start of the same. There is no editing, etc.

Look at this simple snipet

BGDetailTableViewCell * cell= (BGDetailTableViewCell*)[tableView dequeueReusableCellWithIdentifier:[BGDetailTableViewCell reuseIdentifier]];

if (cell==nil)
{
    cell = [[BGDetailTableViewCell alloc]init];
}
else
{
    NSAssert(abs(cell.frame.size.height-cell.contentView.frame.size.height)<=1,@"Should be the same"); //Sometimes this fail
}

NSOrderedSet *Reviews = [self.businessDetailed mutableOrderedSetValueForKey:footer.relationshipKey];
Review * theReview = [Reviews objectAtIndex:row];
cell.theReview = theReview;
NSAssert(abs(cell.frame.size.height-cell.contentView.frame.size.height)<=1,@"Should be the same");//This one never fail right before returning cell
return cell;



`NSAssert(abs(cell.frame.size.height-cell.contentView.frame.size.height)<=1,@"Should be the same")`; never fails right before returning the cell.

However, it fails after I dequeue the cell sometimes latter.

This is the result

(lldb) po cell
$0 = 0x0c0f0ae0 <BGDetailTableViewCell: 0xc0f0ae0; baseClass = UITableViewCell; frame = (0 424; 320 91); hidden = YES; autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0xc01e800>>
(lldb) po cell.contentView
$1 = 0x0c086080 <UITableViewCellContentView: 0xc086080; frame = (10 1; 300 89); gestureRecognizers = <NSArray: 0xc0c7ee0>; layer = <CALayer: 0xc0ebbf0>>

By the way the tableView is in grouped mode. I think that has something to do with it.

like image 547
user4951 Avatar asked Apr 02 '13 03:04

user4951


1 Answers

The two rectangles are in different coordinate systems and will not necessarily match.

cell.frame refers to the cell's rect in its superview's coordinate system (cell.superview) . The cell's superview is the UITableView. The frame of the cell will be manipulated by the table view in order to lay it out properly. This also includes modifying the height to match its rowHeight property or the value returned by tableView:heightForRowAtIndexPath: delegate method.

The contentView of the cell is "inside" of the cell. It's superview is the cell itself which has its own local coordinate system for its subviews. These are not manipulated by the tableView, but by constraints set out on it by the cell (such as your cell subclass) itself. Your subclass may implement layoutSubviews in order to size the contentView the way you want.

If you want to ensure your contentView matches the height (and bounds) of your cell, in your UITableViewCell subclass, implement layoutSubviews like so:

-(void)layoutSubviews
{
    self.contentView.frame = self.bounds;
}

You can make any modifications to the contentView frame that you want, but consider that these should be done with respect to the local coordinate system using the superview's bounds instead of the frame.

like image 165
Mark Avatar answered Oct 21 '22 09:10

Mark