4

There were auto-resizable table view cells introduced in iOS8 (WWDC Session 226 What's new in table and collection views). In my project I'm trying to implement old fixed rows height behavior. Also, the most important thing for me is to inset default cell.contentView frame with margins on the left and right side. So, I change the cell.contentView.frame property and immediately after that the -[cell setNeedsLayout] method is being called and and it leads to cell get stuck in an infinite layoutSubviews loop.

Steps to reproduce:

  1. Create new single view project and replace default view controller with the table view controller

  2. Disable table view automatic height calculation

-(void)viewDidLoad { [super viewDidLoad]; self.tableView.estimatedRowHeight = 0; self.tableView.rowHeight = 44; } 3. Drop a custom cell in the table view in storyboard,

  1. Add any subview to the custom cell:enter image description here,

  2. Subclass the cell and change contentView.frame in layoutSubviews,

  3. Build and run.

Result: Simulator ends up in a black screen stuck in a infinite layout subviews loop.

Expected Result: Simulator displaying a table view with a cell's contentView having a custom frame.

Comment: While debugging a little bit, I found that the infinite loop can be avoided if the cell does not have any custom subviews dropped on it. So it seems the bug will appear after the following conditions are met:

  • self.tableView.estimatedRowHeight = 0; self.tableView.rowHeight = 44;
  • cell.contentView.frame = CGRectMake(...)
  • cell have custom subviews dropped on it in xib or storyboard

Apple does not have the issue in the "Known issues" list for iOS8, so I'm wondering is it actually a bug in iOS8 or does anybody know how to resolve the issue?

chebur
  • 614
  • 8
  • 16

2 Answers2

2

This is not a bug: setNeedsLayout will be called any time you change view's frame.

My guess is that changing cell.contentView.frame also changes cell.bounds in iOS 8, triggering relayout. This behavior may be different between iOS versions; anyway, those are standard views, so we shouldn't change them in unsupported ways.

Rather than operating on cell.contentView, how about adding a custom view with insets to it? Or simply creating a height constraint?

ilya n.
  • 18,398
  • 15
  • 71
  • 89
  • Why does `setNeedsLayout` gets called on the cell itself while it's only a `cell.contentView.frame` that has changed? On iOS6 and iOS7 there is no such `setNeedsLayout` calls. – chebur Jul 08 '14 at 12:38
  • @chebur, I've already added a likely explanation and possible solutions, main point that these are Apple's views, so their internal workings may change. – ilya n. Jul 08 '14 at 12:42
  • 1
    @ilyan. AutoLayout constraint is definitely the way to go. This can still be done within `layoutSubviews` without too much trouble. – Dean Kelly Sep 22 '14 at 16:43
0

In ViewDidLoad please use the below line and there is no need to give the row height

-(void)viewDidLoad {
        [super viewDidLoad];
        self.tableView.estimatedRowHeight = 44.0f;
        self.tableView.rowHeight = UITableViewAutomaticDimension;
}
Arasuvel
  • 2,971
  • 1
  • 25
  • 40