4

I created a UITableViewCell in a storyboard, and used auto layout to position everything in hopes of having iOS 8 automatically determine the cell height for me. My cell has two labels, one of which is a multiline label with a Preferred Width of Automatic.

For reference, the height of the cell is 208, but the height is set to "Default". The table view's row height is set to 208.

In view did load, I run the following code:

self.tableView.estimatedRowHeight = 100;
self.tableView.rowHeight = UITableViewAutomaticDimension;

This works fine the first time I display the cells, everything appears correctly. The problem is if a cell is reused, it will stretch things incorrectly. Based off of this post, I noticed that I may need to run the following code in cellForIndexPath:

[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];

However, when I add that code, I get the message:

Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one  
    you don't want. Try this: (1) look at each constraint and try to figure  
    out which you don't expect; (2) find the code that added the unwanted  
    constraint or constraints and fix it. (Note: If you're seeing  
    NSAutoresizingMaskLayoutConstraints that you don't understand, refer  
    to the documentation for the UIView property  
    translatesAutoresizingMaskIntoConstraints) 
(
    [...]
    "<NSLayoutConstraint:0x7fd108dd1ce0 UITableViewCellContentView:0x7fd108d03d00.height ==>"
)

In this particular case, I noticed that my <tableViewCell> did not have a <rect> tag, and that is why it was outputting height==. (More on the <rect> tag below...)

Questions

  • Is it true that I need to call setNeedsUpdateConstraints and updateConstraintsIfNeeded in cellForRow? If so, why is that? I am not updating any constraints programatically. I have created projects before with multiline labels resizing inside of UITableViewCells which worked seemingly perfectly without that code.

Odd behavior with <rect> tag

This seems to be related to weird behavior regarding the <rect> tag within a <tableViewCell>. Specifically, it may or may not exist, and if it does exist, its height may be set to weird values which may cause issues down the line.

Here are some of the odd behaviors I have noticed...

1. Dragging a brand new UITableViewController from the Object Library creates a cell as follows:

<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="VVy-eG-5ZD">
    <autoresizingMask key="autoresizingMask"/>
    <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="VVy-eG-5ZD" id="o4d-7b-psa">
        <autoresizingMask key="autoresizingMask"/>
    </tableViewCellContentView>
</tableViewCell>

Shows "Default" as the Row Height in the Size Inspector.

Notice how there is no <rect> tag.

2. Dragging a UITableViewCell from the Object Library into that table view controller creates it as follows:

<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="SxR-MB-xdu">
    <rect key="frame" x="0.0" y="0.0" width="600" height="44"/>
    <autoresizingMask key="autoresizingMask"/>
    <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="SxR-MB-xdu" id="JDB-Ys-OoE">
        <autoresizingMask key="autoresizingMask"/>
    </tableViewCellContentView>
</tableViewCell>

Shows "Default" as the Row Height in the Size Inspector.

Notice how there IS a <rect> tag, and that it chose 44 as its height. 44 happens to be the default value for Row Height of the table view in the Size Inspector.

3. Change Row Height Property in the Size Inspector of the Table View to 100.

The cells become bigger visually, but their xml is untouched.

For reference, here is what the TABLE VIEW's xml looks like before:

<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="qea-mf-mRA">
    <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>

... and here's what it looks like after:

<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="100" sectionHeaderHeight="22" sectionFooterHeight="22" id="qea-mf-mRA">
    <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>

The only thing that has changed is the rowHeight="100" from rowHeight="44".

4. Drag another cell from the Object Library in to the Table View

Even though the table view's Row Height is now at 100, we still get the 44 height in the <rect> tag:

<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="wcV-YB-1eG">
    <rect key="frame" x="0.0" y="0.0" width="600" height="44"/>
    <autoresizingMask key="autoresizingMask"/>
    <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="wcV-YB-1eG" id="xM8-zX-Nrh">
        <autoresizingMask key="autoresizingMask"/>
    </tableViewCellContentView>
</tableViewCell>

5. Resizing the cell in the Storyboard to make it visually smaller (to 55)

This adds a new rowHeight="55" property to the <tableViewCell> tag, but leaves the <rect> untouched:

<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="55" id="wcV-YB-1eG">
    <rect key="frame" x="0.0" y="0.0" width="600" height="44"/>
    <autoresizingMask key="autoresizingMask"/>
    <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="wcV-YB-1eG" id="xM8-zX-Nrh">
        <autoresizingMask key="autoresizingMask"/>
    </tableViewCellContentView>
</tableViewCell>

If you look at the Row Height property in the Size Inspector, it now says 55, instead of "Default".

6. Creating a brand new Master Detail Project

This creates a <rect> tag:

<tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="2pz-XF-uhl" style="IBUITableViewCellStyleDefault" id="m0d-ak-lc9">
    <rect key="frame" x="0.0" y="86" width="320" height="44"/>
    <autoresizingMask key="autoresizingMask"/>

Notice how even though the storyboard uses size classes, and thus everything is at 600 width, it still chose 320 width. Also note that we get the same exact result no matter if we choose to create the template for iPhone or Universal.

Summary

Is the <rect> tag created?

  • Creating a UITableViewController: NO
  • Creating a project from the Master-Detail template: YES
  • Dragging a UITableViewCell from the Object Library: YES

Questions

  • Should the rect tag exist?
  • If so, what should the height be set to?
  • Is there a way to add/remove/modify the rect tag via Interface Builder without touching the xml directly?

For my original cell, this is what happens when I change the rect tag manually:

A. If I remove the <rect> tag altogether

Outputs:

Unable to simultaneously satisfy constraints ...
"<NSLayoutConstraint:0x7fb51430b220 UITableViewCellContentView:0x7fb514309340.height ==>"

B. Setting the <rect> to a small height

If I set the value to anything between 1 through 65, I get the following error message.

In this test, I used:

<rect key="frame" x="0.0" y="0.0" width="600" height="44"/>

Outputs:

Unable to simultaneously satisfy constraints ...
"<NSLayoutConstraint:0x7fe3104ce760 UITableViewCellContentView:0x7fe3104e00d0.height == 44>"

C. Setting the <rect> to a large height

If I set the rect to something above 65, it outputs nothing to the console.

In this test, I used:

<rect key="frame" x="0.0" y="0.0" width="600" height="999"/>

In addition to not outputting constraint warnings, everything looks correct.

Questions

  • How do I know which value to set on any given cell?

I will create a sample project that displays these issues soon.

Community
  • 1
  • 1
Senseful
  • 86,719
  • 67
  • 308
  • 465

1 Answers1

0

Trying adding this when you complete the animation:

[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
[cell layoutIfNeeded];
Shawn
  • 667
  • 8
  • 19